0

私は学習しようとしてasync/awaitいるので、これはばかげた質問のように聞こえるかもしれませんが、現在、基本的な TCP サーバーに取り組んでおり、async/await手動スレッドの代わりに使用して複数の接続を処理しようとしています。

クラスには、NetworkClient次のメソッドがあります。

    public async Task Start()
    {
        using (var reader = new StreamReader(_socket.GetStream()))
        {
            while (_server.IsRunning)
            {
                try
                {
                    var content = await reader.ReadLineAsync().ConfigureAwait(false);
                    if (content == null)
                    {
                        Console.WriteLine("Client {0} disconnected", _id);
                        return;
                    }

                    Console.WriteLine("Client {0} wrote: {1}", _id, content);
                }
                catch (IOException)
                {
                    Console.WriteLine("Client {0} disconnected", _id);
                    return;
                }
            }
        }
    }

クライアント接続をリッスンするループには、次のコードが含まれています。

    private void ListenForClients()
    {
        var numClients = 0;
        while (IsRunning)
        {
            var tcpClient = _listener.AcceptTcpClient();
            var netClient = new NetworkClient(this, tcpClient, numClients);
            netClient.Start();

            Console.WriteLine("Client {0} Connected", numClients);
            numClients++;
        }
    }

これは期待どおりに機能し、複数の telnet 接続が同時にサーバーに接続してメッセージを送信できるようにします。awaitただし、 resharper は、追加する必要があることを教えてくれnetClient.Start();ます。そうしないとブロックされないからです。でも、ブロックしたくない!

Resharper がこのような警告を発しているという事実は、async/awaitシステムへのアプローチが間違っているのではないかと考えさせられます。Resharper がこのコード行に追加する必要があるのはなぜですか? また、他の tcp 接続の参加をブロックしないようawaitに、これを使用する正しい方法は何ですか?netClient.Start();

4

2 に答える 2

4

ただし、resharper は、netClient.Start(); に await を追加する必要があることを教えてくれます。そうしないとブロックされないからです。でも、ブロックしたくない!

通常はエラーであるため、ReSharper はこの状況について警告します。

あなたの場合、メソッドprivate Taskを表すタイプでメンバーを作成し、Startそれではなく割り当てることができますawait

startTask = netClient.Start();

これにより、警告が回避され、Startメソッドがいつ終了するかを判断し、スローされた例外を検出できるようになります。

于 2013-04-22T17:44:18.730 に答える
0

メソッドは実際には非同期ではありませんStart-接続が同期的に発生するのを待ってから、非同期的にデータを読み取るように見えます。その結果、コードはListenForClients実際に期待どおりに機能します-Start前に終了する同期部分Console.WriteLine(したがって、正しいテキストを出力します)および非同期部分は、誰も結果を待たずに単独で実行されます。

このコードは、基本的に「接続 + 起動し、データの読み取りを処理する新しいスレッドを忘れる」と同じです。

async/await非同期操作でシーケンシャル コードを記述する必要がある場合に役立ちます。あなたの場合、並列操作が本当に必要です-複数のリスナーを開始するよりも、他の構成の方がおそらく良いでしょう。各リスナーのコードは、使用することでメリットが得られる可能性がありますawait-イベントを伴う複数の状態 (またはさらに悪い EndSend/SendReceive...) の代わりに、ループで await read/await write を使用する方がはるかに簡単です。

于 2013-04-22T04:02:28.457 に答える