2010-09-27 51 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