Verwendung von UdpClient.BeginReceive in einer Schleife

8

Ich möchte das tun

%Vor%

Aber anstatt UdpClient.Receive zu verwenden, muss ich UdpClient.BeginReceive verwenden. Das Problem ist, wie mache ich das? Es gibt nicht viele Beispiele, die BeginReceive verwenden, und das MSDN-Beispiel hilft überhaupt nicht. Soll ich BeginReceive verwenden oder einfach unter einem separaten Thread erstellen?

Ich erhalte immer ObjectDisposedException Ausnahme. Ich bekomme nur die ersten Daten gesendet. Die nächsten Daten werden eine Ausnahme auslösen.

%Vor%

Was gibt's?

Übrigens ist die allgemeine Idee:

  1. Erstellen Sie den tcpclient-Manager.
  2. Beginnen Sie mit dem Senden / Empfangen von Daten mit udpclient.
  3. Wenn alle Daten gesendet wurden, signalisiert der tcpclient-Manager dem Empfänger, dass alle Daten gesendet wurden, und die Verbindung zum udpclient sollte geschlossen werden.
Syaiful Nizam Yahya 07.11.2010, 14:47
quelle

5 Antworten

4

Es scheint, dass UdpClient.BeginReceive() und UdpClient.EndReceive() nicht gut umgesetzt sind. Und sicherlich verglichen mit der Implementierung des TcpListeners, ist es viel schwieriger zu verwenden.

Es gibt mehrere Dinge, die Sie tun können, um mit UdpClient.Receive() besser für Sie zu arbeiten. Erstens ermöglicht das Setzen von Timeouts auf dem zugrunde liegenden Socket-Client, dass die Steuerung durchläuft (zu einer Ausnahme), wodurch der Steuerungsfluss fortgesetzt oder beliebig geloopt werden kann. Zweitens können Sie durch das Erstellen des UDP-Listeners für einen neuen Thread (dessen Erstellung ich nicht gezeigt habe) den Semi-Blocking-Effekt der UdpClient.Receive() -Funktion vermeiden, und Sie können den Thread später effektiv abbrechen, wenn Sie dies richtig tun .

Der folgende Code besteht aus drei Teilen. Der erste und der letzte Teil sollten sich in der Hauptschleife an den Ein- und Ausstiegspunkten befinden. Der zweite Teil sollte in dem neuen Thread sein, den Sie erstellt haben.

Ein einfaches Beispiel:

%Vor%

Außerdem können Sie UdpClient.Available > 0 überprüfen, um festzustellen, ob UDP-Anforderungen vor der Ausführung von UdpClient.Receive() in die Warteschlange gestellt wurden. Dadurch wird der Blockierungsaspekt vollständig entfernt. Ich schlage vor, dass Sie dies mit Vorsicht versuchen, da dieses Verhalten nicht in der Microsoft-Dokumentation angezeigt wird, aber scheint zu funktionieren.

Hinweis:

Der MSDN-Exmaplcode Sie haben möglicherweise gefunden, während die Erforschung dieses Problems eine zusätzliche benutzerdefinierte Klasse - UdpState. Dies ist keine .NET-Bibliotheksklasse. Dies scheint eine Menge Leute zu verwirren, wenn sie dieses Problem erforschen.

Die Zeitüberschreitungen müssen nicht unbedingt Sie können festlegen, dass Ihre App vollständig beendet wird. Sie können jedoch andere Aktionen in dieser Schleife ausführen, anstatt sie für immer zu blockieren.

Der Befehl listener.Close () ist wichtig, da er den UdpClient dazu zwingt Wirf eine Ausnahme und beende die Schleife, damit Thread.Abort () behandelt werden kann. Ohne diese Option können Sie den Listener-Thread möglicherweise nicht ordnungsgemäß beenden, bis das Zeitlimit überschritten wird oder ein UDP-Paket empfangen wird, das dazu führt, dass der Code über den UdpClient.Receive () - Block hinaus fortgesetzt wird.

Nur um diese unbezahlbare Antwort hinzuzufügen, hier ist ein funktionierendes und getestetes Codefragment. (Hier in einem Unity3D-Kontext, aber natürlich für jedes c #.)

%Vor%     
PretorianNZ 19.02.2014 23:23
quelle
2

Ich denke, Sie sollten es nicht in einer Schleife verwenden, sondern rufen immer BeginReceive auf, wenn Sie den BeginReceive-Callback aufrufen, und Sie behalten eine öffentliche Variable für count, wenn Sie die Zahl auf 100 begrenzen möchten.

    
A_Nablsi 07.11.2010 14:51
quelle
2

schauen Sie zuerst auf MSDN. Sie bieten ein gutes Beispiel. Ссылка

    
Captain Comic 07.11.2010 14:52
quelle
2

Ich würde Netzwerkkommunikation in einem Hintergrundthread durchführen, so dass es nichts anderes in Ihrer Anwendung blockiert.

Das Problem mit BeginReceive ist, dass Sie EndReceive an einem bestimmten Punkt aufrufen müssen (sonst haben Sie Warte-Griffe nur herum) - und der Aufruf von EndReceive wird blockiert, bis der Empfang beendet ist. Deshalb ist es einfacher, die Kommunikation einfach auf einen anderen Thread zu legen.

    
davisoa 07.11.2010 14:54
quelle
0

Sie müssen Netzwerkoperationen, Dateimanipulationen und andere Dinge durchführen, die von anderen Dingen abhängig sind, als von Ihrem eigenen Programm in einem anderen Thread (oder Aufgabe ), weil sie Ihr Programm einfrieren können. Der Grund dafür ist, dass Ihr Code sequenziell ausgeführt wird. Sie haben es in einer Schleife verwendet, die nicht in Ordnung ist. Wenn BeginRecieve callback aufgerufen wird, sollten Sie es erneut aufrufen. Sehen Sie sich den folgenden Code an:

%Vor%     
Media 20.10.2017 20:39
quelle

Tags und Links