Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

C# Named Pipes with Async

0.00/5 (No votes)
16 Aug 2012 2  
A message server using named pipes and the Async CTP library (async and await keywords)

Introduction

The following code shows how to implement a named pipe message server using the async and await keywords for local out-of-proc communication between applications.

Background

I wanted to create an application that showed how to use named pipes for out-of-proc communication between two .NET applications. While creating the application, I starting investigating asynchronous calling of the message send and receive methods - this lead to the inclusion of Async CTP library v3.0 (which can be found here). The Async library was not easy to install and this link was very helpful.

Using the Code

Warning!

You will need to set up the Async CTP v3 before running the code. You will also need to re-reference the AsyncCTPLibrary.dll - which by default is located within your My Documents folder.

The Send Message Method

The send message method uses the async keyword in the method signature to enable asynchronous calling. Firstly, create the named pipe client (with the given name on the local server), then a stream writer to write to the pipe's stream. Then connect and write the message to the stream. The writing to the stream is done using the await keyword.

public static async void SendMessageAsync(string pipeName, string message)
{
    try
    {
        using (var pipe = new NamedPipeClientStream(LOCAL_SERVER, pipeName, 
		PipeDirection.Out, PipeOptions.Asynchronous))
        using (var stream = new StreamWriter(pipe))
        {
            pipe.Connect(DEFAULT_TIME_OUT);

            // write the message to the pipe stream 
            await stream.WriteAsync(message);
        }
    }
    catch (Exception exception)
    {
        OnSendMessageException(pipeName, new MessengerExceptionEventArgs(exception));
    }
}

The Listening Method

The listening method also uses the async keyword in the method signature to enable asynchronous calling. Firstly, create the named pipe server (with the given name), then wait for a connection - this is done asynchronously using the await keyword. Once a connection is made, create a stream reader on the pipe, and read from the stream - again asynchronously using the await keyword. Once the message is received, then invoke the action (called messageRecieved), and disconnect the pipe. The whole process is wrapped in a while(true) loop so that new messages can be continually received.

public static async void StartListeningAsync(string pipeName, Action<string> messageRecieved)
{
    try
    {
        while (true)
        {
            using (var pipe = new NamedPipeServerStream(pipeName, 
		PipeDirection.In, 1, PipeTransmissionMode.Byte, PipeOptions.Asynchronous))
            {
                // wait for the connection
                await pipe.WaitForConnectionAsync();

                using (var streamReader = new StreamReader(pipe))
                {
                    // read the message from the stream - async
                    var message = await streamReader.ReadToEndAsync();
                    if (messageRecieved != null)
                    {
                        // invoke the message received action 
                        messageRecieved(message);
                    }
                }

                if (pipe.IsConnected)
                {
                    // must disconnect 
                    pipe.Disconnect();
                }
            }
        }
    }
    catch (Exception exception)
    {
        OnSendMessageException(pipeName, new MessengerExceptionEventArgs(exception));
    }
} 
Usage

To use the message server, call the message server static method, SendMessageAsync using the TaskEx.Run method - this will invoke the send message on a separate thread, allowing the UI to continue to run uninterrupted.

TaskEx.Run(() => MessageServer.SendMessageAsync(pipeName, message));

To listen for messages, call the message server static method, StartListeningAsync using the TaskEx.Run method - this will invoke the listening on a separate thread. When a message is received, the action parameter (messageReceived) will be called. In this case, we want to show a message box back on the UI thread so we must Invoke a new Action on the Forms UI thread.

TaskEx.Run(() => MessageServer.StartListeningAsync(pipeName, messageReceievd =>
{
    Invoke((Action)(() => 
    {
        var message = String.Format("Original Message:=\n\n{0}\nServer 
			details:=\n\nSending to pipe:={1}\nListening on pipe:={2}",
                messageReceievd,
                txtSendPipeName.Text,
                txtListenPipeName.Text);

        MessageBox.Show(this, message, "Message Received");
    }));
}));

How to Run and Test

To run, create two instances of the application (either by running the .exe twice or starting two instances from within Visual Studio - Debug -> Start new instance). Then enter in App 1 the "Send Pipe Name" as "ping" and the "Listening Pipe Name" as "pong". In App 2, enter "pong" and "ping".

Then click the start button on each application, then hit the test button to send messages between the two applications.

Points of Interest

The Async CTP library is really cool and makes async coding a lot easier to write and to read, but most of all much more fun.

Name pipes are a simple and easy way to send messages between two applications on a desktop.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here