Using WTDawson.EventPipes to update UI from a service

Just in case you haven’t read my other article about WTDawson.EventPipes, I suggest you read it before reading this.

WTDawson.EventPipes is a library built in C# that is designed for inter-process communication (Communication between two different processes) and is event based, this means that one side could fire an event which is received by the other side and data gets carried across.

If you have one side of this running in a Windows service or background task and one side running in a frontend of some kind (For example, a WPF (Windows Presentation Foundation) Application), they can communicate with each other.
For sending structured data, I suggest sending data as JSON, this can be done by using Newtonsoft.Json and converting a string to an array of bytes, which can be done using the default encoding built into .NET.

Example usage

Here’s an example of how you could use WTDawson.EventPipes to achieve event-based inter-process communication.
This example uses two one-way event pipes instead of the usual EventPipe.

  • Create a new Windows Service or Console Application, this will serve as the backend.
  • Navigate to where the entry point for the application is and modify the code below to fit your needs.
// At the root (Remove static if not needed)
using System.Text;
using System.Threading.Tasks;
using WTDawson.EventPipes;

static OneWayEventPipe.Server server;
static OneWayEventPipe.Client client;

// Example entry point
static void Main(string[] args)
{
  // Create the two one-way event pipes
  server = new OneWayEventPipe.Server("SERVER_A");
  client = new OneWayEventPipe.Client("SERVER_B");
  
  // Open the connection on the server and attempt to connect to the other server
  server.OpenConnection();
  client.ConnectAsync(int.MaxValue);
  
  // "connected" and "disconnected" are system events ("Once")
  server.Once("connected", () =>
  {
      Console.WriteLine("Server side connected (Server A)");
  });
  server.Once("disconnected", () =>
  {
      Console.WriteLine("Client side disconnected (Server A)");
      server.OpenConnection();
  });
  client.Once("connected", () =>
  {
      Console.WriteLine("Client side connected (Server B)");
  });
  client.Once("disconnected", () =>
  {
      Console.WriteLine("Client side disconnected (Server B)");
  });
  
  // These are user defined events ("On")
  client.On("ping", (byte[] data) => {
    // Send data like this
    server.Send("pong", []);
  });
  
  client.On("status", (byte[] data) => {
    server.Send("status", Encoding.Default.GetBytes("Working"));
  });
}

Now for example, this is how you could do the other side of this.

// At the root (Remove static if not needed)
using System.Text;
using System.Threading.Tasks;
using WTDawson.EventPipes;

static OneWayEventPipe.Server server;
static OneWayEventPipe.Client client;

// Example entry point
static void Main(string[] args)
{
  // Create the two one-way event pipes
  server = new OneWayEventPipe.Server("SERVER_B"); // Make sure these are swapped around
  client = new OneWayEventPipe.Client("SERVER_A");
  
  // Open the connection on the server and attempt to connect to the other server
  server.OpenConnection();
  client.ConnectAsync(int.MaxValue);
  
  // "connected" and "disconnected" are system events ("Once")
  server.Once("connected", () =>
  {
      Console.WriteLine("Server side connected (Server A)");
  });
  server.Once("disconnected", () =>
  {
      Console.WriteLine("Client side disconnected (Server A)");
      server.OpenConnection();
  });
  client.Once("connected", () =>
  {
      Console.WriteLine("Client side connected (Server B)");
  });
  client.Once("disconnected", () =>
  {
      Console.WriteLine("Client side disconnected (Server B)");
  });
  
  // These are user defined events ("On")
  client.On("ping", (byte[] data) => {
    // Send data like this
    server.Send("pong", []);
  });
  
  client.On("status", (byte[] data) => {
    Console.WriteLine("Received status: {0}", Encoding.Default.GetString(data));
  });
  
  server.Send("status", []); // Send "status" event (Can be used as a request)
}

Do note however, the bigger the amount of data, the more time it takes to send.

Recommendations/Suggestions

  • I suggest using a shared class library between the two projects so it makes it easier to serialize and deserialize it.
  • For a front end that can be disconnected, I suggest automatically opening the backend again once it has disconnected.
  • If the back end of your project is crucial to the functionality of your application, I suggest telling the user (with something like a popup) when the back end has disconnected.
  • I suggest adding something that allows the back end to make popups/notifications on the front end so it can more easily communicate problems to the user.

Loading


Discover more from WTDawson

Subscribe to get the latest posts sent to your email.

Leave a Reply