2014-04-25 108 views
0

目前,我已经使用演示代码http://msdn.microsoft.com/en-us/library/bb546085.aspx实现了命名管道。而不是同步客户端;不过,我想让它异步。下面是我的实现,其中主要的程序使StartClientNamedPipeListening(通话):async NamedPipeClientStream实现反馈

/// <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(); 
     } 
    } 

该工程的实施,根据我的测试;然而,我想知道,我是否做了一些明显的禁忌?有没有人对如何更好地实施它有任何建议? TIA。

+0

这似乎很适合代码审查:http://codereview.stackexchange.com/ – attila

+0

我不认为我有权移动它。你知道如何将这篇文章转移到该论坛吗? – Roger

+1

当然,有一个明显的缺陷。它*完全*无法使用BeginRead(),然后阻塞,直到收到响应。只需调用Read()。如果你的意思是异步的,那么这个并不紧密,这意味着“不要等待”。 –

回答

0

以下是我如何修改代码以使其异步工作。我不知道为什么我认为我需要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(); 
     } 
    } 

谢谢,汉斯。

+1

为什么不使用TPL和'Task.Factory.FromAsync'? – Noseratio

+0

我不熟悉Task.Factory,但感谢您的建议。我得看看它。 – Roger

+0

实际上,一个首选的方法就是在'async' /'await'中使用'NamedPipeClientStream.ReadAsync'和'NamedPipeClientStream.WriteAsync'。 – Noseratio