Task.Delayは、I / O操作のように本当に非同期ですか?つまり、スレッドではなくハードウェアと割り込みに依存していますか?

Dec 09 2020

私はすべてが茂みの周りを打ち負かすたくさんの関連コンテンツを見つけました、そして私は答えを見つけることができませんでした。Task.Delay(int)このコードは16個の論理プロセッサしか搭載していないマシンで実行できるため、スレッドを使用しないことはほぼ100%確信しています。

var tasks = new List<Task>();
for(int i = 1; i < 100000; i++) tasks.Add(Task.Delay(10000));
await Task.WhenAll(tasks);

そして、完了するのに10秒かかります。およそ10万のスレッドを使用しているとしたら、かなり時間がかかると思います。

だから私の質問はどのように機能するのTask.Delay(int)ですか?ていないことのように、この悪い-題するSOの質問を示しますが、スレッドとハードウェア資源の観点から。

回答

4 StephenCleary Dec 11 2020 at 12:24

.NETの現在の実装では、管理されたタイマーインスタンスを追跡し、適切なタイミングでそれらのイベントを発生させる単一の「タイマースレッド」があります。このタイマースレッドは、次のタイマーの期限に設定されたタイムアウトで制御信号をブロックします。制御信号はタイマーの追加/削除/変更に使用されるため、このブロッキングリクエストがタイムアウトすると、タイマースレッドは次のタイマーが起動したことを認識します。これは通常のスレッドブロック操作であるため、内部的には、スレッドはアイドル状態になり、そのブロック操作が完了するかタイムアウトになるまでスケジューラキューから削除されます。これらの操作のタイムアウトは、OSスケジューラのタイマー割り込みによって処理されます。

したがって、技術的にはスレッドがありますが、プロセスごとに1つのスレッドだけであり、ごとに1つのスレッドではありませんTask.Delay

これは.NETの現在の実装にあることを再度強調します。CPUごとに1つのタイマースレッド、またはタイマースレッドの動的プールなど、他のソリューションが提案されています。おそらく、彼らは実験され、何らかの理由で拒否されたか、あるいは将来、代替ソリューションが採用されるでしょう。AFAIKこれはどこにも公式に文書化されていないので、これは実装の詳細です。