私はC++が専門でC#はそれほど詳しくないのですが、委託先が作成したC#のコードを動かしたところ問題が発生しているので、原因の調査をしています。そこで、ぶち当たった疑問について質問させて下さい。
await Task.Run(...)すると、呼び出し側スレッドはそのTaskが終わるの待つを思いますが、待っている間呼び出し側スレッドは何をしているのでしょうか?
- 何もせず、ただTaskの完了を待っている(Taskからのイベントやメッセージなどを待っているだけ)
- 呼び出し元でTimerが定義されている場合、時間が来るとawait中でもタイマー関数が呼ばれる
- 呼び出し元スレッドが何らかの非同期処理(ネットワーク処理やディスクI/Oなど)を実行していた場合、それらの完了イベントが実行される
- 呼び出し元がUIを持つスレッドの場合(メインスレッドなど)、メッセージループが回っていてWindowsへのメッセージが処理される
- その他・・・
どうぞよろしくお願いします。
await Task.Run の呼び出し前、呼び出し中、呼び出し後に Thread.CurrentThread.ManagedThreadId を表示すればわかります。
ThreadIdを見ると何が分かるというのでしょうか?
await Task.Run呼び出し中に、呼び出されたTaskの中で何が行われているか?という質問ではなく、呼び出し中に呼び出したスレッド自体が何をしているのかという質問なので、「呼び出し中」で待っている時にManagedThreadIdを表示させることは不可能です。
呼び出し前と呼び出し後であればManagedThreadIdを見ることはできますが、それを見ることで「何が」分かるのかをご教示くださいませんか?
意味が分かりませんか?
using System;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApp1
{
class Program
{
static async Task Main(string[] args)
{
Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
await Task.Run(() =>
{
Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
});
Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
}
}
}
これを実行すればわかります。
提示いただいたコードから分かることは、呼び出し前と呼び出し後のスレッドは同じであること、Task.Runの中で実行されているスレッドはそれとは異なるスレッドあること、この2点だと思います。
少し言い換えます、Task.Runが別スレッドで実行されている間、呼び出し元スレッドは単にそのスレッドの終了を待っているだけなのか、他に何かやっていることはあるのではないか?という質問です。
なので私の質問では、提示していただいたコードのawait Task.Runの中にあるConsole.WriteLine処理(および同じ関数内でのすべての処理)も、await Task.Runの外にある2つのConsole.WriteLine部分の処理についても関心がなく、尋ねてもいません。
違います。あなたの思っているような実行結果にはなりません。実行してから言ってください。
実行したらわかると言いましたが、実行せず頭の中で想像してわかるとは誰も言っていません。
違わないと思います。あなたにコードを提示してもらう以前にそういうことは確認しています。
何が「違う」のか教えて下さい。
実行結果を書いてください。そのうえでわからないとしたら、一度寝て目を覚ましてから行ったほうがいいと思います。そうとう寝ぼけています。
と言っても絶対実行しないと決めているようなので、結果を書きましょうか。
await 実行前のスレッドはそこで終了し、実行中のスレッドと実行後のスレッドは同じものになります。
これでもまだ終了を待つとかどうとかいう発想になるのであれば、本気で寝たほうがいいと思います。
Windows Forms で、イベントハンドラの中で呼んだ場合、呼び出し元のスレッドはイベントハンドラから戻ってメッセージループに戻ります。ユーザーコードから離れることを tamoto さんは「フリーになる」と表現しています。
コンソールアプリとUIでは、何かのモデルが違ってて、awaitの内部的な動きも違ってたような気がしますけど...具体的な話でなくて申し訳ありませんが...
これ結構難しい話なので、コードベースでないと話が噛み合わないような気がしますよ
Zuishin さんが上のコメントに書かれたコードを試してみました。
> 実行中のスレッドと実行後のスレッドは同じものになります。
時々 1 ⇒ 3 ⇒ 4 と言うようにすべて違うスレッドになることもあるようです。