この質問にはすでに答えがあります。
私は学ぶことをしようとしています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接続で同時にサーバーに接続してメッセージを送信することができます。しかし、resharperは私に追加すべきだと私に言いますawaitにnetClient.Start();それ以外の場合はブロックされませんので。しかし、私はそれをブロックしたくありません!
Resharperが私にこのような警告を与えているという事実は、私が私に近づいているのかどうか疑問に思います。async/awaitシステムが正しくありません。 Resharperはなぜ私に追加してほしいのですかawaitこのコード行に、そしてこれを使用する正しい方法は何ですかnetClient.Start();するではない他のTCP接続が参加するのをブロックしますか?
しかし、resharperは、netClient.Start()にwaitを追加する必要があることを教えてくれます。それ以外の場合はブロックされませんので。しかし、私はそれをブロックしたくありません!
これは通常エラーであるため、ReSharperはこの状況について警告します。
あなたのケースでは、あなたはprivate Taskを表すあなたの型のメンバーStartメソッドではなく、それを割り当てるawaitそれ:
startTask = netClient.Start();
これは警告を回避し、いつあなたがStartメソッドは終了し、それがスローした例外を検出します。
君はStartmethodは実際には非同期ではありません - 非同期でデータを読み取るよりも同期して接続が行われるのを待つように見えます。結果としてあなたのコードはListenForClients実際には期待通りの動作をします - 同期部分Start前に終了Console.WriteLine(だから正しいテキストを出力する)そして非同期部分は誰も結果を待たずにそれ自身で動くだろう。
このコードは基本的に「connect + fireして新しいスレッドを忘れてデータの読み込みを処理する」と同じです。
async/await非同期操作でシーケンシャルコードを書く必要があるときに輝きます。あなたの場合、あなたは本当に並列操作を必要としています - 他の構造は、おそらく複数のリスナーを起動するのにより良いでしょう。各リスナーのためのコードはおそらく使うことの恩恵を受けるでしょうawait - イベントを含む複数の状態の代わりに、ループ内でawait read / await writeを使用するほうがはるかに簡単です(または、さらに悪いEndSend / SendReceive ...)。
Startmethodはクライアントを同期的に探すことを目的としていますが、クライアントが接続されると、そのクライアントのデータを非同期的に待つ必要があります。それが私が持っていることであり、それはうまくいきます。問題は、resharperが私に望んでいることですawait netClient.Start();これにより、クライアントからの新しい入力を待っているときに同期的にブロックされ、新しいtcpクライアントを受け付けないようになります。 - KallDrexxawiat-ingasyncあなたが壊れて見えるコードを書いている関数 - あなたはそれが大丈夫な理由を説明するコードに半ページコメントを入れなければなりません。 Startを2つの関数に分けて、新しいスレッドで明示的に読書を始めるようにしてください。注:"同期"を使用していると思います。 2つの意味で - 1つの「現在のスレッドでブロッキング待機」 (Startの最初の部分がどのように振る舞うか)そして私の関数の中の別の"コードはその点を越えて移動することはなく、潜在的に操作はスレッドをブロックしないで終了します(どうやってawait振る舞う)。 - Alexei Levenkov
async何もしなくても(前も、時には後も)await。それはコンパイラにそれを伝えているだけですawaitメソッドで使用される可能性があります - Gennady Vanin Геннадий ВанинStart()方法は明らかにawaitそれを呼び出します。問題は、非同期ではないメソッドが非同期メソッドを呼び出していることです。バンドResharperは、それが望んでいる動作ではないとしても、私はそれを待つべきだと確信しています。 - KallDrexxasyncメソッドawait体内で - Gennady Vanin Геннадий Ванин