2010-09-27 27 views
6

我找不到一个很好的示例,说明如何创建异步运行的可重用命名管道侦听器。我可以做一个可重复使用的监听器:如何实现异步运行的可重用的命名管道侦听器?

NamedPipeServerStream pipeServer = new NamedPipeServerStream("MyPipe", PipeDirection.InOut); 

    while (true) 
    { 
      pipeServer.WaitForConnection(); 

      StreamReader reader = new StreamReader(pipeServer); 

      MessageBox.Show(reader.ReadLine()); 

      pipeServer.Disconnect(); 
    } 

,我可以做一个听者台异步:

NamedPipeServerStream pipeServer = new NamedPipeServerStream("MyPipe", PipeDirection.InOut, 1, PipeTransmissionMode.Message, PipeOptions.Asynchronous); 

    pipeServer.BeginWaitForConnection((a) => 
    { 
     pipeServer.EndWaitForConnection(a); 

     StreamReader reader = new StreamReader(pipeServer); 
     MessageBox.Show(reader.ReadLine()); 

    }, null); 

但我似乎无法得到这两个去。这是否有一个很好的例子?我还担心部分发送的消息,因为我认为这是异步通信的问题。

更新: 我更接近一点。

pipeServer = new NamedPipeServerStream("MyPipe", PipeDirection.InOut, 1, PipeTransmissionMode.Message, PipeOptions.Asynchronous); 

pipeServer.BeginWaitForConnection((a) => 
{ 
    pipeServer.EndWaitForConnection(a); 

    StreamReader reader = new StreamReader(pipeServer); 

    while (running) 
    { 
     String text = reader.ReadLine(); 

     if (String.IsNullOrEmpty(text) == false) 
     { 
      MessageBox.Show(text); 
     } 
    } 

    MessageBox.Show("Done!"); 

}, null); 

这将读取成功一次,并将继续循环,ReadLine在初始成功读取后返回一个空的空字符串。所以它显然不会阻止,并且正在尝试再次阅读。问题是如果我再次发送相同的消息,它不会被拾取,并且我的管道编写者说它正在接收错误2316(尽管我无法弄清楚这意味着什么)。我想我只需要做一些类似这样的事情,每次都会清理管道,就像我列出的第一个代码示例一样,但我还没有完成这项工作。

+0

系统(即Win32 API)错误代码在这里:http://msdn.microsoft.com/en-us/library/ms681381(VS.85).aspx但没有错误2316 ...你确定那是错误代码?你能否包括例外的全部细节(包括类型和消息?) – Richard 2010-09-28 15:54:17

+0

对不起,我直到现在才看到这个,我不再产生这个错误,这是在作者的最后产生它的代码:如果(管== INVALID_HANDLE_VALUE) \t \t { \t \t \t的cout << “错误:” << GetLastError函数(); \t \t} – 2010-09-28 20:12:34

+0

事实证明这是错误231.从别的东西的6输出 – 2010-10-07 18:29:09

回答

6

我想我知道了:

pipeServer = new NamedPipeServerStream("MyPipe", PipeDirection.InOut, 1, PipeTransmissionMode.Message, PipeOptions.Asynchronous); 

Boolean connectedOrWaiting = false; 

Byte[] buffer = new Byte[65535]; 

while (running) 
{ 
    if (!connectedOrWaiting) 
    {     
     pipeServer.BeginWaitForConnection((a) => { pipeServer.EndWaitForConnection(a); }, null); 

     connectedOrWaiting = true; 
    } 

    if (pipeServer.IsConnected) 
    { 
     Int32 count = pipeServer.Read(buffer, 0, 65535); 

     if (count > 0) 
     { 
      UTF8Encoding encoding = new UTF8Encoding(); 
      String message = encoding.GetString(buffer, 0, count); 

      MessageBox.Show(message); 
     } 

     pipeServer.Disconnect(); 

     connectedOrWaiting = false; 
    } 
} 

,因为他们来此将接受多个消息,跑步设置为false(在另一个线程,很明显)会尽快关闭。这似乎是我需要的。有人可以证实我没有做任何愚蠢的事情吗?

2

I'm also concerned about partially sent messages

它们不是使用本机(Win32)API的NamedPipes的问题,所以我非常怀疑它们是使用.NET的问题。然而,在native documentation它说:

Data is written to the pipe as a stream of messages. The pipe treats the bytes written during each write operation as a message unit. The GetLastError function returns ERROR_MORE_DATA when a message is not read completely. This mode can be used with either PIPE_READMODE_MESSAGE or PIPE_READMODE_BYTE.

(注意:ERROR_MORE_DATA为234)

该文档还指出,对标志FILE_FLAG_OVERLAPPED(的PipeOptions.Asynchronous天然等价物):

Overlapped mode is enabled. If this mode is enabled, functions performing read, write, and connect operations that may take a significant time to be completed can return immediately.

我总是对异步命名管道使用异步IO操作(即Stream.BeginRead),但这确实意味着失去了TextReader的功能,但后来使用了无论如何,被定义为传输字节组。

+1

。那很好知道。我对BeginRead很开放,但我认为我没有正确使用它。我建立了连接,但读取的字节数(从EndRead返回)始终为0.您是否知道一个很好的示例?最好是可重复使用的一个? – 2010-09-28 19:45:16