5

I have multiple applications running on a single machine. One is doing work and writing logs to disk about what it has done (I'll call this WorkerApp) and another that summarizes support information about the status of WorkerApp along with some more details (I'll call this Dashboard).

From the Dashboard i want to instruct the WorkerApp to take an action (say, "Ping remote services") and I would like the WorkerApp to send the Dashboard the "pong" response when it gets it.

I have seen examples of using the SendMessage, but this seems to be pretty archaic (isn't there anything more standard now in 2016 for between process communications?).

I have very little experience with Akka.Net but the Remoting feature of it seem like a good approach, although setting this up seems a little overkill for what I would like to do.

What is the easiest way currently to go about communicating between two processes in .Net? And is there some examples of this, working on a localmachine?

Dennis Christian
  • 186
  • 1
  • 14
XenoPuTtSs
  • 1,254
  • 1
  • 11
  • 31
  • Akka.NET can, or you can use MSMQ... any message buses basically is how you do IPC – Callum Linington Jun 24 '16 at 13:03
  • 1
    "Overkill" is relative. If you have any solution it in place, you probably want more (like security, reliability, remote (as in different computers), etc.). Adding all such things to a homegrown solution based on primitives (like raw pipes, etc.) is no easy endeavor. I would use an existing technology, the Akka.NET or even WCF. – Christian.K Jun 24 '16 at 13:06
  • @Christian.K I know "overkill" was a subjective term. It is really how I feel currently with Akka.net since I do not have much experience with it. I will probably be experimenting with Akka.net Remoting to solve this problem, but I wanted to get a feel to see if others have already went down this road and had a bad experience. – XenoPuTtSs Jun 24 '16 at 13:12
  • Possible duplicate of "[IPC Mechanisms in C# - Usage and Best Practices](http://stackoverflow.com/questions/56121/ipc-mechanisms-in-c-sharp-usage-and-best-practices)" – Scott Chamberlain Jun 24 '16 at 13:39

3 Answers3

2

I put together an Akka.Net example for this. This is what it looks like.

DashBoard (sends messages)

using System;
using Akka.Actor;
using Akka.Configuration;

namespace DashBoard
{
    class Program
    {
        static void Main(string[] args)
        {
            var config = ConfigurationFactory.ParseString(@"
akka {  
    actor {
        provider = ""Akka.Remote.RemoteActorRefProvider, Akka.Remote""
    }
    remote {
        helios.tcp {
            transport-class = ""Akka.Remote.Transport.Helios.HeliosTcpTransport, Akka.Remote""
            applied-adapters = []
            transport-protocol = tcp
            port = 0
            hostname = localhost
        }
    }
}
");

            using (var system = ActorSystem.Create("Dashboard", config))
            {
                var server = system.ActorSelection("akka.tcp://WorkerApp@localhost:8081/user/WorkerAppActor");
                while (true)
                {
                    var input = Console.ReadLine();
                    server.Tell(input);
                }
            }
        }
    }
}

WorkerApp (receives messages)

using System;
using Akka.Actor;
using Akka.Configuration;

namespace WorkerApp
{
    class Program
    {
        static void Main(string[] args)
        {
            var config = ConfigurationFactory.ParseString(@"
akka {  
    actor {
        provider = ""Akka.Remote.RemoteActorRefProvider, Akka.Remote""
    }
    remote {
        helios.tcp {
            transport-class = ""Akka.Remote.Transport.Helios.HeliosTcpTransport, Akka.Remote""
            applied-adapters = []
            transport-protocol = tcp
            port = 8081
            hostname = localhost
        }
    }
}
");

            using (var system = ActorSystem.Create("WorkerApp", config))
            {
                system.ActorOf<WorkerAppActor>("WorkerAppActor");

                Console.ReadLine();
            }
        }
    }

    class WorkerAppActor : TypedActor, IHandle<string>
    {
        public void Handle(string message)
        {
            Console.WriteLine($"{DateTime.Now}: {message}");
        }
    }
}
XenoPuTtSs
  • 1,254
  • 1
  • 11
  • 31
1

Have a look at .Net remoting. It's a bit more modern than SendMessage, but not a whole lot. It's pretty easy to use though. I think the official way to do this these days is probably using WCF, but I'm pretty sure it's just the same under the hood.

.Net remoting supports various channels (Http, TCP), but in your case I'd suggest IPC remoting. It sits on top of named pipes.

Probably easiest if you google (.Net remoting), but the general idea is to define a class in your "server" app derived from MarshalByRefObject. Once you've done that, register it with the remoting infrastructure using RemotingConfiguration.RegisterWellKnownServiceType.

Your client app can then create an instance of the class using Activator.CreateObject and then you're good to go.

One thing to be aware of: it looks like you'll want a callback mechanism - so your Dashboard isn't blocked waiting for your WorkerApp. This is supported in .Net remoting, but you'll need to create two channels - one for the outgoing calls (from Dashboard to WorkerApp) and then another for the incoming callbacks.

Another suggestion: your worker class (the one derived from MarshalByRefObject) will be easier to deal with if exposes an interface as well. Put that interface in a DLL available to both apps and life will be easier.

Ian of Oz
  • 116
  • 7
  • 2
    .NET Remoting is not recommended for new development, to [quote the MSDN](https://msdn.microsoft.com/en-us/library/kwdt6w2k(v=vs.100).aspx): "*This topic [.Net Remoting] is specific to a legacy technology that is retained for backward compatibility with existing applications and is not recommended for new development. Distributed applications should now be developed using the [Windows Communication Foundation (WCF)](http://go.microsoft.com/fwlink/?LinkID=127777).*" – Scott Chamberlain Jun 24 '16 at 13:37
  • WCF is just as easy to configure as .NET remoting, you can even do it [without configuration files](http://weblogs.asp.net/ralfw/a-truely-simple-example-to-get-started-with-wcf). – Scott Chamberlain Jun 24 '16 at 13:41
  • @ScottChamberlain thanks for the links, ill check them out. – XenoPuTtSs Jun 24 '16 at 13:42
  • True... that's why I mentioned WCF, albeit not very strongly. I know WCF is now the preferred way, but I like the simplicity of .Net remoting and it sounds like the use case here is pretty simple. – Ian of Oz Jun 24 '16 at 13:44
  • Ditto on the thanks for the link @ScottChamberlain - obviously time I had a refresher, just never had an issue with .Net Remoting that forced me to move onto WCF. – Ian of Oz Jun 24 '16 at 13:52
1

One suggestion may be to use a database or other persistent storage to create a type of 'Queue' which the dashboard can insert tasks into. This could also store statuses about the tasks which can be updated by the worker process. Although this could be considered 'overkill' it brings a vartiety of benefits such as auditing, historical reporting and server crash/power-off redundancy. It would also probably make scaling up the application in the future easier.

Milney
  • 6,253
  • 2
  • 19
  • 33