12

方法を検討してくださいSocket.BeginSend()。2 つのスレッド プール スレッドがこのメソッドを同時に呼び出すと、それぞれのメッセージが混ざり合うことになりますか、それともソケット クラスがこれを回避しますか?

4

2 に答える 2

16

.NET Socketインスタンスは、一部のメソッド(同じメソッドまたは異なるメソッド)を同時に呼び出すと、一貫性のない状態が発生する可能性があるため、スレッドセーフではありません。ただし、メソッドBeginSend()BeginReceive()メソッドは、それ自体に関してスレッドセーフです。

それぞれ(または両方)に複数の未処理の呼び出しがあるのは安全です。

の場合、BeginReceive()と呼ばれる順序でデータが利用可能になったときにサービスが提供されます。これは、たとえば、処理に時間がかかるが、他の受信をできるだけ早く実行したい場合に役立ちます。もちろん、この場合、コードで複数のレシートを同時に処理し、アプリケーションの状態を保護するために独自の同期ロジックが必要になる場合があります。

の場合BeginSend()、各呼び出しは送信されたデータをソケットバッファーにプッシュしようとし、そこで受け入れられるとすぐに、コールバックが呼び出されます(ここでを呼び出しますEndSend())。呼び出しに十分なバッファスペースがない場合、ブロックされます。

BeginSend()注:デフォルトの8kバッファーが、「正確に8kのデータですばやく呼び出すことができ、ブロックされる」という意味であると想定しないでください。次のことが当てはまります。

  1. 8Kは「公称サイズ」の数値であり、バッファが縮小および拡大する可能性があります

  2. 8K相当の通話をキューに入れると、データがネットワーク上に送信され、キューに入れられたデータの8Kが削減されます。

一般に:

  • BeginSend()スレッド内で複数回呼び出すと、センドは呼び出された順序でマシンを離れることが保証されます。

  • 複数のスレッドから呼び出す場合BeginSend()、他のブロッキングメカニズムを使用して実際の呼び出しを特定の順序で強制的に行わない限り、順序は保証されません。ただし、各呼び出しは、ネットワークバイトの1つの連続したストリームでデータを適切に送信します。

于 2012-04-20T23:28:59.110 に答える
7

MSDN フォーラムで、あなたの質問に答えているような投稿を見つけました。

  1. 複数の BeginSend を同時にキューに入れることができます。ロックする必要はありません

編集:

さらに興味深い情報:

MSDN doc BeginSend()の備考セクションを少し下にスクロールすると、関連する可能性のあるコールバック メソッドの興味深い使用法が見つかります。

[...] BeginSend メソッドを呼び出した後に元のスレッドをブロックする場合は、WaitHandle.WaitOne メソッドを使用します。[...]

于 2012-04-13T18:58:53.583 に答える