title: Efficient communication between two .Net applications
body: <p>I am currently writing a .Net application in c#, which has two main components:</p>
  
  <ol>
  <li><strong>DataGenerator</strong> -a component generating a lot of data</li>
  <li><strong>Viewer</strong> - a WPF application that is able to visualize the data that the generator creates</li>
  </ol>
  
  <p>Those two components are currently two seperate projects in my solution. Furthermore, I am using the <strong>PRISM 4.0</strong> framework in order to make modules out of those components. </p>
  
  <p>Essentially, the DataGenerator generates a lot of data and sends out events using the <strong>EventAggregator</strong> from PRISM and the Viewer subscribes to these events and shows the data ready for the user.</p>
  
  <p>Now my requirements have slightly changed and the two components will now run in their own application (but on the same computer). I would still like to have all the communication event-driven and I would also still like to use the PRISM framework.</p>
  
  <p>My first thought was to use <strong>WCF</strong> for the communication between those two applications. However, there is one thing that makes life a bit harder: </p>
  
  <ol>
  <li>the DataGenerator has absolutely <em>no knowledge</em> about the Viewer (<em>and no dependencies</em>)</li>
  <li>the DataGenerator should still be working perfectly fine if we do not have viewer open, or if we close the viewer application.</li>
  <li>a lot of events are currently rising from the DataGenerator (using the EventAggregator): Is WCF efficient enough to handle lots of events in a very short amount of time?</li>
  </ol>
  
  <p>Basically the data that all those events carry are very simple strings, integer and booleans. Could there be a more lightweight way of doing this without WCF?</p>
  
  <p>Finally, it would be nice if the DataGenerator could send out these events and potentially more than one application subscribes to them (or none).</p>
  
  <p>Any suggestions and hints are highly appreciated.</p>
  
  <p>Thanks!
  Christian</p>
  
  <p><strong>EDIT 1</strong></p>
  
  <p>I am now creating two simple Console applications (one hosting the service and sending the messages, another one receiving the messages) using WCF and Callbacks (as has been suggested). I will add working code as soon as I get this working.</p>
  
  <p><strong>EDIT 2</strong></p>
  
  <p>Okay - Managed to get a simple program running! :) Thanks for your help, guys! Here is the code and a picture of where which classes are:</p>
  
  <p><img src="https://i.stack.imgur.com/Bt4R6.jpg" alt="enter image description here"></p>
  
  <p><strong>Let's start with the sender:</strong></p>
  
  <p>In my application, the sender contains the service interfaces and their implementations. </p>
  
  <p>IMessageCallback is the callback interface:</p>
  
  <pre><code>namespace WCFSender
  {
      interface IMessageCallback
      {
          [OperationContract(IsOneWay = true)]
          void OnMessageAdded(string message, DateTime timestamp);
      }
  }
  </code></pre>
  
  <p>ISimpleService is the service contract:</p>
  
  <pre><code>namespace WCFSender
  {
      [ServiceContract(CallbackContract = typeof(IMessageCallback))]
      public interface ISimpleService
      {
          [OperationContract]
          void SendMessage(string message);
  
          [OperationContract]
          bool Subscribe();
  
          [OperationContract]
          bool Unsubscribe();
      }
  }
  </code></pre>
  
  <p>SimpleService is the implementation of ISimpleService:</p>
  
  <pre><code>public class SimpleService : ISimpleService
      {
          private static readonly List&lt;IMessageCallback&gt; subscribers = new List&lt;IMessageCallback&gt;();
  
          public void SendMessage(string message)
          {
              subscribers.ForEach(delegate(IMessageCallback callback)
              {
                  if (((ICommunicationObject)callback).State == CommunicationState.Opened)
                  {
                      callback.OnMessageAdded(message, DateTime.Now);
                  }
                  else
                  {
                      subscribers.Remove(callback);
                  }
              });
          }
  
          public bool Subscribe()
          {
              try
              {
                  IMessageCallback callback = OperationContext.Current.GetCallbackChannel&lt;IMessageCallback&gt;();
                  if (!subscribers.Contains(callback))
                      subscribers.Add(callback);
                  return true;
              }
              catch
              {
                  return false;
              }
          }
  
          public bool Unsubscribe()
          {
              try
              {
                  IMessageCallback callback = OperationContext.Current.GetCallbackChannel&lt;IMessageCallback&gt;();
                  if (!subscribers.Contains(callback))
                      subscribers.Remove(callback);
                  return true;
              }
              catch
              {
                  return false;
              }
          }
      }
  </code></pre>
  
  <p>In Program.cs (on the sender side), the Service is hosted and the messages are being send:</p>
  
  <pre><code>[CallbackBehavior(ConcurrencyMode = ConcurrencyMode.Multiple)]
      class Program : SimpleServiceReference.ISimpleServiceCallback, IDisposable
      {
          private SimpleServiceClient client;
  
          static void Main(string[] args)
          {
              ServiceHost myService = new ServiceHost(typeof(SimpleService));
              myService.Open();
              Program p = new Program();
              p.start();
  
              Console.ReadLine();
          }
  
          public void start()
          {
              InstanceContext context = new InstanceContext(this);
  
              client = new SimpleServiceReference.SimpleServiceClient(context, "WSDualHttpBinding_ISimpleService");
  
              for (int i = 0; i &lt; 100; i++)
              {
                  client.SendMessage("message " + i);
                  Console.WriteLine("sending message" + i);
                  Thread.Sleep(600);
              }
          }
  
          public void OnMessageAdded(string message, DateTime timestamp)
          {
              throw new NotImplementedException();
          }
  
          public void Dispose()
          {
              client.Close();
          }
      }
  </code></pre>
  
  <p><em>Furthermore, note that the service reference has been added to the Sender project!</em></p>
  
  <p><strong>Lets now get to the Receiver side:</strong></p>
  
  <p>As has already been done in the Sender, I added the Service Reference to the project.</p>
  
  <p>There is only one class, Program.cs:</p>
  
  <pre><code>[CallbackBehavior(ConcurrencyMode = ConcurrencyMode.Multiple)]
      class Program : SimpleServiceReference.ISimpleServiceCallback, IDisposable
      {
          private SimpleServiceClient client;
  
          static void Main(string[] args)
          {
              Program p = new Program();
              p.start();
              Console.ReadLine();
              p.Dispose();
          }
  
          public void start()
          {
              InstanceContext context = new InstanceContext(this);
  
              client = new SimpleServiceReference.SimpleServiceClient(context, "WSDualHttpBinding_ISimpleService");
              client.Subscribe();
          }
  
          public void OnMessageAdded(string message, DateTime timestamp)
          {
              Console.WriteLine(message + " " + timestamp.ToString());
          }
  
          public void Dispose()
          {
              client.Unsubscribe();
              client.Close();
          }
      }
  </code></pre>
  
  <p>The last thing remaining are the app.config files. On the client side, the app.config is automatically generated by adding the service reference. On the server side, I have slightly changed the config, however parts of it are also auto-generated by adding the service reference. Note that you need to do the changes before adding the service reference:</p>
  
  <pre><code>&lt;?xml version="1.0" encoding="utf-8" ?&gt;
  &lt;configuration&gt;
      &lt;system.serviceModel&gt;
          &lt;bindings&gt;
              &lt;wsDualHttpBinding&gt;
                  &lt;binding name="WSDualHttpBinding_ISimpleService" closeTimeout="00:01:00"
                      openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
                      bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard"
                      maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
                      messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true"&gt;
                      &lt;readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
                          maxBytesPerRead="4096" maxNameTableCharCount="16384" /&gt;
                      &lt;reliableSession ordered="true" inactivityTimeout="00:10:00" /&gt;
                      &lt;security mode="Message"&gt;
                          &lt;message clientCredentialType="Windows" negotiateServiceCredential="true"
                              algorithmSuite="Default" /&gt;
                      &lt;/security&gt;
                  &lt;/binding&gt;
              &lt;/wsDualHttpBinding&gt;
          &lt;/bindings&gt;
          &lt;client&gt;
              &lt;endpoint address="http://localhost:8732/Design_Time_Addresses/WCFSender/SimpleService/"
                  binding="wsDualHttpBinding" bindingConfiguration="WSDualHttpBinding_ISimpleService"
                  contract="SimpleServiceReference.ISimpleService" name="WSDualHttpBinding_ISimpleService"&gt;
                  &lt;identity&gt;
                      &lt;dns value="localhost" /&gt;
                  &lt;/identity&gt;
              &lt;/endpoint&gt;
          &lt;/client&gt;
          &lt;behaviors&gt;
              &lt;serviceBehaviors&gt;
                  &lt;behavior name="MessageBehavior"&gt;
                      &lt;serviceMetadata httpGetEnabled="true" /&gt;
                      &lt;serviceDebug includeExceptionDetailInFaults="false" /&gt;
                  &lt;/behavior&gt;
              &lt;/serviceBehaviors&gt;
          &lt;/behaviors&gt;
          &lt;services&gt;
              &lt;service name="WCFSender.SimpleService" behaviorConfiguration="MessageBehavior"&gt;
                  &lt;endpoint address="" binding="wsDualHttpBinding" contract="WCFSender.ISimpleService"&gt;
                      &lt;identity&gt;
                          &lt;dns value="localhost" /&gt;
                      &lt;/identity&gt;
                  &lt;/endpoint&gt;
                  &lt;endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" /&gt;
                  &lt;host&gt;
                      &lt;baseAddresses&gt;
                          &lt;add baseAddress="http://localhost:8732/Design_Time_Addresses/WCFSender/SimpleService/" /&gt;
                      &lt;/baseAddresses&gt;
                  &lt;/host&gt;
              &lt;/service&gt;
          &lt;/services&gt;
      &lt;/system.serviceModel&gt;
  &lt;/configuration&gt;
  </code></pre>
  
  <p><strong>IMPORTANT:
  I managed to implement these two very simple applications using the tutorials. The above code works for me and hopefully helps others to understand WCF callback. It is not extremely well-written code and should not be used entirely! It is just a simplistic example app.</strong></p>