Question

Presently, I have implemented named pipes using demo code from http://msdn.microsoft.com/en-us/library/bb546085.aspx. Instead of the synchronous client; however, I want to make it asynchronous. Here is my implementation, where the main program makes a call to StartClientNamedPipeListening():

    /// <summary>
    /// Buffer where received bytes or bytes received are stored 
    /// </summary>
    private byte[] _byteBuffer = null;

    /// <summary>
    /// Callback result for reading data from the named pipe
    /// </summary>
    private IAsyncResult _pipeResult;

    /// <summary>
    /// Named object to send and receive data to and from watchdog
    /// </summary>
    NamedPipeClientStream _pipeClient;

    /// <summary>
    /// Notifies waiting threads that an event has occurred
    /// </summary>
    protected ManualResetEvent _pipeReadDone = new ManualResetEvent(false);

    private object _pipeState = new object();

    private void StartClientNamedPipeListening()
    {
            // open and then close the gate as soon as after one thread passed,
            // i.e., put the event into a non-signaled, or closed, state:
            _pipeReadDone.Reset();

            // Reads the data coming in from the pipe and call the 
            // thread safe delegate to get the data received.
            _byteBuffer = new Byte[50];
            _pipeResult = _pipeClient.BeginRead(_byteBuffer, 0,
                _byteBuffer.Length, PipeReadCallback, _pipeState);

            // worker thread block in here (waiting for...
            // _pipeReadDone.Set()), i.e., wait for the door to be opened
            _pipeReadDone.WaitOne();            
    }

   private void PipeReadCallback(IAsyncResult ar)
    {
        int bytesRead = 0;

        // if port serial is open and..
        if (_pipeClient.IsConnected)
        {
            // the stream can read then..
            if (_pipeClient.CanRead)
            {
                // wait for asynchronous read to be completed
                bytesRead = _pipeClient.EndRead(ar);
            }
        }

        if (bytesRead > 0)
        {
            StreamString ss = new StreamString(_pipeClient);
            // Validate the server's signature string 
            if (ss.ReadString() == "I am the one true server!")
            {
                // The client security token is sent with the first write. 
                // Send the name of the file whose contents are returned 
                // by the server.
                ss.WriteString(@"C:\Temp\namedpipestring.txt");

                // Print the file to the screen.
                Console.WriteLine(ss.ReadString(), false);
            }
            else
            {
                Console.WriteLine("Server could not be verified.");
            }

            // put the event into a signaled, or open,  state: 
            // open gate for next data
            _pipeReadDone.Set();

            // Start waiting for the next watchdog message
            StartClientNamedPipeListening();
        }
    }

This implementation works according to my tests; however, I was wondering, am I doing some obvious no-no's? Does anyone have any suggestions on how it could possibly be implemented better? TIA.

Was it helpful?

Solution

Here is how I modified the code to get it to work asynchronously. I'm not sure why I thought I needed the ManualResetEvent:

    /// <summary>
    /// Buffer where received bytes or bytes received are stored 
    /// </summary>
    private byte[] _byteBuffer = null;

    /// <summary>
    /// Callback result for reading data from the named pipe
    /// </summary>
    private IAsyncResult _pipeResult;

    /// <summary>
    /// Named object to send and receive data to and from watchdog
    /// </summary>
    NamedPipeClientStream _pipeClient;

    private object _pipeState = new object();

    private void StartClientNamedPipeListening()
    {
            _pipeClient = new NamedPipeClientStream(".", "testpipe",
                PipeDirection.InOut, PipeOptions.Asynchronous,
                TokenImpersonationLevel.Impersonation);
            _pipeClient.Connect();
            // Reads the data coming in from the pipe and call the 
            // thread safe delegate to get the data received.
            _byteBuffer = new Byte[50];
            _pipeResult = _pipeClient.BeginRead(_byteBuffer, 0,
                _byteBuffer.Length, PipeReadCallback, _pipeState);      
    }

   private void PipeReadCallback(IAsyncResult ar)
    {
        int bytesRead = 0;

        // if port serial is open and..
        if (_pipeClient.IsConnected)
        {
            // the stream can read then..
            if (_pipeClient.CanRead)
            {
                // wait for asynchronous read to be completed
                bytesRead = _pipeClient.EndRead(ar);
            }
        }

        if (bytesRead > 0)
        {
            StreamString ss = new StreamString(_pipeClient);
            // Validate the server's signature string 
            if (ss.ReadString() == "I am the one true server!")
            {
                // The client security token is sent with the first write. 
                // Send the name of the file whose contents are returned 
                // by the server.
                ss.WriteString(@"C:\Temp\namedpipestring.txt");

                // Print the file to the screen.
                Console.WriteLine(ss.ReadString(), false);
            }
            else
            {
                Console.WriteLine("Server could not be verified.");
            }

            // Start waiting for the next watchdog message
            StartClientNamedPipeListening();
        }
    }

Thanks, Hans.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top