3

この質問は、デザインやパターン、そしてどちらを使用するかについてではありません。この質問の核心は、スレッドとブロッキングに関して何が起こっているかについてです。

この例は、同じアクションを継続的に実行するように設計されたすべてのブロッキング メソッドに適用されます。この場合、これはネットワーク ストリームでの読み取りまたは書き込みのブロックです。メソッド間のスレッド化とパフォーマンスに関して、舞台裏でかなりの違いはありますか?

私の仮定では、以下の各メソッドはスレッドを作成するか、プールされたスレッドを使用します。次に、読み取るデータが存在するまでそのスレッドをブロックします。そうは言っても、メソッド間のスレッド化、パフォーマンス、およびスケーラビリティに関して、かなりの違いはありますか?

現在、サーバーアプリケーションを作成しています。このアプリケーションには、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());
}
4

1 に答える 1

1

私の仮定では、以下の各メソッドはスレッドを作成するか、プールされたスレッドを使用します。次に、読み取るデータが存在するまでそのスレッドをブロックします。

全くない。最初の 2 つの例はスレッドをブロックしますが、次の 2 つの例は非同期です。

非同期メソッドは、作業を OS のキューに入れ、コールバック (この場合は I/O 完了ポート) を待機することによって機能します。そのため、読み取りが保留中の間、使用されているスレッドはありません。

非同期アプローチはそれほど多くのスレッドを使用しないため、スケーラビリティが向上します。

最後の例 ( async) は、最初の例と同じくらい単純であり、Rx または TPL データフローを使用しない限り、このアプローチをお勧めします。ソケット通信を行う場合、コネクション断検出などのエラーハンドリングを考えると、明らかに非同期通信の方が有利です。

于 2013-02-25T04:28:54.917 に答える