0

UDP パケットからデータを受信し、それをファイルに書き込むソフトウェアを作成しています。これは、UdpClient クラスをテストするためにコンソール アプリケーションとして作成したサンプル コードです。

while(!done)
{
Console.WriteLine("Receiving");
byte[] bytes = listener.Receive(ref groupEP);
Console.WriteLine("Received");
}

UDP パケットが受信されない場合、while ループが Receive(ref groupEP) 関数で一時停止することがわかりました。UDP パケットが受信された場合にのみ、「Received」の出力に進みます。

ただし、実際のプログラム (WPF) では、リソースを節約するために、代わりにタイマーを使用しています。現在、インターフェイスとファイルを更新するために正常に動作していますが、タイマーが 100 ミリ秒ごとに呼び出され、UDP パケットが 1 秒ごとにしか受信されない場合にどうなるか疑問に思っていました (UDP をいつ受信するか分からないと仮定します)。だから私は100ミリ秒を選択します)。これにより、1 秒ごとに 9 回の冗長なタイマー呼び出しが発生し、オーバーフローが発生することはありませんか? 現在、アプリケーションはこのシーンで正常に動作していますが、その理由と、考えられる結果があるかどうかを理解したいと思います。

4

1 に答える 1

0

この質問は「広すぎる」境界線です。あなたはかなりの数の異なる問題を提起しました。とはいえ、物事を短くしようとしている…

タイマーの動作は、実際に使用したタイマーによって異なります。タイマー イベント ハンドラーを使用DispatcherTimerして呼び出しReceive()ている場合は、代わりに UI スレッドをブロックするため、冗長なタイマー イベントは取得されません。これは実際にはまったく良くありませんが、少なくともタイマー イベントが多すぎるという結果にはなりません。

他の種類のタイマーを使用している場合は、そうです...前のReceive()操作を完了する前に新しい操作を発行すると、まだ完了していない操作の数が増え続けReceive()ます。ソケットをノンブロッキング モードにすることでこれを修正できますが、それではまったく新しいワームの缶が開かれてしまいます。そう…


実際、ブロッキングReceive()メソッドを使用したり、I/O 関連の目的でタイマーを使用したりしないでください。コールバックを処理する代わりに使用できるように、 でラップできる などReceiveFrom()のの非同期バージョンを使用する必要があります。(受信したデータグラムのリモート エンドポイント情報を実際に取得できるように使用する必要があります)。BeginReceiveFrom()Task.Factory.FromAsync()awaitReceiveFrom()

この手法を使用する場合、 でループするawaitか ( を使用している場合) 、完了した操作を処理するときに再度FromAsync()呼び出します(古いスタイルのコールバック メカニズムを使用している場合)。BeginReceiveFrom()これにより、一度に 1 つの受信操作のみをアクティブにすることができますが、スレッドをブロックすることはまったくないため、タイマーやその他のメカニズムを使用してソケットをポーリングする必要はありません。

于 2015-11-16T01:49:36.693 に答える