この質問にはすでに答えがあります。
私は学ぶことをしようとしています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
メソッドは終了し、それがスローした例外を検出します。
君はStart
methodは実際には非同期ではありません - 非同期でデータを読み取るよりも同期して接続が行われるのを待つように見えます。結果としてあなたのコードはListenForClients
実際には期待通りの動作をします - 同期部分Start
前に終了Console.WriteLine
(だから正しいテキストを出力する)そして非同期部分は誰も結果を待たずにそれ自身で動くだろう。
このコードは基本的に「connect + fireして新しいスレッドを忘れてデータの読み込みを処理する」と同じです。
async
/await
非同期操作でシーケンシャルコードを書く必要があるときに輝きます。あなたの場合、あなたは本当に並列操作を必要としています - 他の構造は、おそらく複数のリスナーを起動するのにより良いでしょう。各リスナーのためのコードはおそらく使うことの恩恵を受けるでしょうawait
- イベントを含む複数の状態の代わりに、ループ内でawait read / await writeを使用するほうがはるかに簡単です(または、さらに悪いEndSend / SendReceive ...)。
Start
methodはクライアントを同期的に探すことを目的としていますが、クライアントが接続されると、そのクライアントのデータを非同期的に待つ必要があります。それが私が持っていることであり、それはうまくいきます。問題は、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 Геннадий Ванин