2009-07-20 10 views
1

ich dieses Stück Code bin mit einer Verbindung zu einem Server zu verarbeiten und Daten vom ClientTcpClient und Network entsorgen Problem

using(var client = _listener.EndAcceptTcpClient(ar)) 
{ 
     var clientStream = client.GetStream(); 
     // Get the request message 
     Messages.ReceiveMessage(clientStream, msg => ProcessRequest(msg, clientStream)); 
} 

Jetzt lesen, die ReceiveMessage Methode ruft BeginRead() auf den Stream als Parameter übergeben , aber ich bekomme eine ObjectDisposedException.

Ich weiß, dass eine Lösung ist, stream.Dispose() aufzurufen, wenn ich den Stream nicht mehr brauche, aber ich suche wirklich nach einer Lösung, wo ich die using-Klausel beibehalten kann.

Dank

Antwort

3

Hier gibt es zwei Möglichkeiten.

Zuerst können Sie diesen asynchronen Prozess durchführen und bis zum Abschluss blockieren, so dass Sie die using-Anweisung beibehalten können. Dies ist der Ansatz suggested by Ben M here.

Alternativ können Sie die using-Anweisung entfernen und die Client-Variable selbst entfernen. Dies mag umständlicher erscheinen als die Verwendung der Compilersyntax zur Verwendung, bietet aber den Vorteil, dass Sie das asynchrone Verhalten beibehalten können, das Sie gerade in dieser Situation nutzen möchten, und die Notwendigkeit von Blöcken beseitigt. Dies erfordert jedoch, dass Sie die Variable speichern und sie an einem geeigneten Ort (möglicherweise am Ende Ihres Delegaten) ablegen, aber das erfordert wahrscheinlich auch, dass Sie sie später überprüfen, nur für den Fall, dass der Delegat nie aufgerufen wird.

Die "using" -Anweisung in C# ist großartig, aber es gibt Situationen, in denen es nicht angemessen ist, und dies kann einer von ihnen sein (wenn Sie das asynchrone Verhalten beibehalten müssen).

2

Sie können dies tun:

using (var client = _listener.EndAcceptTcpClient(ar)) 
{ 
    var clientStream = client.GetStream(); 

    using (var eh = new ManualResetEvent(false)) 
    { 
     // Get the request message 
     Messages.ReceiveMessage(clientStream, msg => 
      { 
       ProcessRequest(msg, clientStream); 
       eh.Set(); 
      }); 

     eh.WaitOne(); 
    } 
} 

Ein Nachteil: Wenn es irgendwo sinnvoll ist (eine Instanz der Klasse), um die Manual zu speichern, so dass sie wiederverwendet werden können, tun so - seit viele davon zu schaffen/zu zerstören kann ein wenig schweinisch sein.

Beachten Sie auch, dass ich von dem Verhalten, das Sie in Ihrem Post beschreiben, annehmen, dass ReceiveMessage() eine asynchrone Operation ist.

+0

ManualResetEvent implementiert IDisposable so mit diesem Muster sollte in einer using-Anweisung verpackt werden. – Joe

+0

Dies "bricht" jedoch die asynchrone Verarbeitung der Daten, da Sie grundsätzlich blockieren, bis der asynchrone Prozess abgeschlossen ist. Das mag nicht in allen Situationen wünschenswert sein. –

+0

Ich habe die Frage innerhalb der gegebenen Einschränkungen beantwortet. :-) Joe hat recht, wenn er() das ManualResetEvent verwendet. –