この質問は、デザインやパターン、そしてどちらを使用するかについてではありません。この質問の核心は、スレッドとブロッキングに関して何が起こっているかについてです。
この例は、同じアクションを継続的に実行するように設計されたすべてのブロッキング メソッドに適用されます。この場合、これはネットワーク ストリームでの読み取りまたは書き込みのブロックです。メソッド間のスレッド化とパフォーマンスに関して、舞台裏でかなりの違いはありますか?
私の仮定では、以下の各メソッドはスレッドを作成するか、プールされたスレッドを使用します。次に、読み取るデータが存在するまでそのスレッドをブロックします。そうは言っても、メソッド間のスレッド化、パフォーマンス、およびスケーラビリティに関して、かなりの違いはありますか?
現在、サーバーアプリケーションを作成しています。このアプリケーションには、TCP 接続を作成する 1000 のクライアントがあります。これらの接続は開いたままになり、少量のデータを頻繁に送受信します。実装が最も簡単で保守が容易なモデル A の使用を検討しています。どのパターンを選んでも 1000 スレッドになるのでしょうか?
これらのメソッドは、構造を理解するためのものであり、適切なストリーミング読み取り、タイムアウト、および例外処理なしで使用されるものではないことに注意してください。
方法 A: ブロッキング
Task.Factory.StartNew(ReadMessage,TaskCreationOptions.LongRunning);
private void ReadMessage()
{
while(true)
{
TcpClient.Read();
}
}
方法B:睡眠
Task.Factory.StartNew(ReadMessage,TaskCreationOptions.LongRunning);
private void ReadMessage()
{
while(true)
{
if(TcpClient.DataAvailable)
TcpClient.Read();
else
Thread.Sleep(1);
}
}
方法 C: 再帰的開始/終了
private void ReadMessage()
{
stream.BeginRead(readCallBack)
}
private void readCallBack()
{
stream.EndRead();
stream.BeginRead(readCallBack)
}
方法 D: BCL socket.ReceiveAsync() からの非同期
private void readCallBack()
{
while(true)
{
await socket.ReceiveAsync(eventArgs);
}
}
メソッド E: 読み取りをブロックする非同期メソッド (メソッド D を使用して呼び出しますが、BCL からソケットの組み込みの拡張機能を使用する代わりにカスタム メソッドです)
private async Task<byte[]> ReceiveAsync()
{
return await Task.Factory.StartNew(() => TcpClient.Read());
}