2010-09-27 10 views
6

Ich kann kein gutes Beispiel für die Erstellung eines wiederverwendbaren Named Pipe-Listeners finden, der asynchron ausgeführt wird. Ich kann einen wiederverwendbaren Hörer machen:Wie implementieren Sie einen wiederverwendbaren Named Pipe-Listener, der asynchron ausgeführt wird?

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

    while (true) 
    { 
      pipeServer.WaitForConnection(); 

      StreamReader reader = new StreamReader(pipeServer); 

      MessageBox.Show(reader.ReadLine()); 

      pipeServer.Disconnect(); 
    } 

und ich kann einen asychronous Zuhörer machen:

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); 

Aber ich kann nicht beides in Gang zu bringen scheine. Gibt es dafür ein gutes Beispiel? Ich bin auch besorgt über teilweise gesendete Nachrichten, da ich glaube, dass dies ein Problem mit asynchroner Kommunikation wie folgt ist.

Aktualisieren: Ich bin ein wenig näher.

Das wird einmal erfolgreich gelesen und wird fortgesetzt, während ReadLine nach dem ersten erfolgreichen Lesevorgang eine leere Zeichenfolge zurückgibt. Es blockiert also eindeutig nicht und versucht erneut zu lesen. Das Problem ist, wenn ich die gleiche Nachricht ein zweites Mal sende, wird es nicht abgeholt, und mein Rohrschreiber sagt, dass es Fehler 2316 empfängt (obwohl ich nicht herausfinden kann, was das bedeutet). Ich denke, ich muss nur etwas Ähnliches tun, wo die Pipe jedes Mal aufgeräumt wird, wie das erste Codebeispiel, das ich aufgelistet habe, aber ich habe das noch nicht zum Laufen gebracht.

+0

System (dh Win32 API) Fehlercodes sind hier: http://msdn.microsoft.com/en-us/library/ms681381(VS.85).aspx Aber es gibt keinen Fehler 2316 ... sind Sie sicher das war der Fehlercode? Könnten Sie alle Details der Ausnahme (einschließlich Typ und Nachricht?) Hinzufügen? – Richard

+0

Entschuldigung, ich habe das erst jetzt gesehen, und ich produziere den Fehler nicht mehr. Dies ist der Code, der es am Ende des Schreibers erzeugte: if (Rohr == INVALID_HANDLE_VALUE) \t \t { \t \t \t cout << "Fehler:" << GetLastError(); \t \t} –

+0

es stellt sich heraus, es war Fehler 231. Die 6 ausgegeben wurde, von etwas anderem –

Antwort

6

Ich glaube, ich habe es:

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; 
    } 
} 

Dies wird mehrere Nachricht akzeptieren, wie sie kommen, und wird so schnell heruntergefahren, wie Laufen auf false gesetzt ist (in einem anderen Thread, natürlich). Es scheint zu sein, was ich brauche. Kann jemand bestätigen, dass ich nichts Dummes mache?

2

I'm also concerned about partially sent messages

Sie sind kein Problem mit NamedPipes die native (Win32) APIs verwenden, so dass ich bezweifle sehr, sie sind ein Problem .NET. Doch in der native documentation es sagt:

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.

(Hinweis ERROR_MORE_DATA ist 234.)

Die Dokumentation sagt auch, für Flag FILE_FLAG_OVERLAPPED (das native Äquivalent 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.

I habe immer asynchrone IO-Operationen mit asynchronen Named Pipes verwendet (zB Stream.BeginRead), aber das bedeutet, dass ich die Funktionalität eines TextReader verloren habe, aber dann PipeTransmissionMode.Message ist in Bezug auf die Übertragung von Gruppen von Bytes ohnehin definiert.

+1

. Nun, das ist gut zu wissen.Ich bin sehr offen für BeginRead, aber ich glaube nicht, dass ich es richtig benutze. Ich stelle meine Verbindung her, aber die Anzahl der gelesenen Bytes (die Rückgabe von EndRead) ist immer 0. Kennen Sie ein gutes Beispiel? Vorzugsweise eines, das wiederverwendbar ist? –