Click here to Skip to main content
15,868,141 members
Articles / Programming Languages / C# 4.0
Tip/Trick

C# Named Pipes with Async

Rate me:
Please Sign up or sign in to vote.
4.17/5 (6 votes)
16 Aug 2012CPOL3 min read 62.9K   2.6K   25   8
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.

C#
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.

C#
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.

C#
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.

C#
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".

Image 1

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, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
Australia Australia
http://maddogmikeb.blogspot.com.au/

Comments and Discussions

 
QuestionSlow? Pin
Marcel Monteny8-Nov-12 11:37
Marcel Monteny8-Nov-12 11:37 
Thanks for the great example.

Is it normal that it takes 6 to 7 secondes to receive the sended message (on Windows 7)? Sleepy | :zzz:
Is there a faster way to communicate?
AnswerRe: Slow? Pin
Maddog Mike B8-Nov-12 12:58
Maddog Mike B8-Nov-12 12:58 
GeneralRe: Slow? Pin
Marcel Monteny9-Nov-12 9:30
Marcel Monteny9-Nov-12 9:30 
QuestionDoesn't work in NET 4.5 Pin
Nemo19668-Nov-12 10:14
Nemo19668-Nov-12 10:14 
AnswerRe: Doesn't work in NET 4.5 Pin
Maddog Mike B8-Nov-12 12:50
Maddog Mike B8-Nov-12 12:50 
GeneralRe: Doesn't work in NET 4.5 Pin
Nemo19669-Nov-12 6:55
Nemo19669-Nov-12 6:55 
GeneralRe: Doesn't work in NET 4.5 Pin
Nemo19669-Nov-12 11:11
Nemo19669-Nov-12 11:11 
GeneralMy vote of 5 Pin
Dnx_71-Nov-12 14:03
Dnx_71-Nov-12 14:03 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.