質問: $"Number: {i++}"; } catch (Exception e) { Trace.WriteLine(e.Message); } await Task.Delay(100); } }); ``` この時、Begin1()ではメッセージの更新は常に同じスレッド上で行われますが Begin2()ではawait Task.Delay()の呼び出し後にスレッドが変更されたりされなかったりするのは何故でしょうか。 また、Beginメソッドの様に、何秒かおきに処理するという場合 より良いアプローチはBegin1とBegin2ではどちらですか? (無限ループなのはサンプルの為です)
回答: まずTaskとは結果`T`とそれを得るための操作であり、実行方法は規定していません。操作は短時間に完了し多数実行されることを想定して、既定ではスレッドプールを使用するようです。そのため、`ManagedThreadId`はランダムに切り替わります。 操作が長時間要することが想定される場合は`Task.Factory.StartNew`に`TaskCreationOptions.LongRunning`を指定します。この場合、スレッドプールを使わず新規にスレッドを作成するようです。 これらは別段、仕様として決まっているわけではないので今後、他の実行手段に変更される可能性もあります。あくまで短時間に多数実行される操作を効率よく完了させる/長時間を要する操作を実行する、というオプション指定でしかありません。 繰り返しになりますが、Taskは実行方法を規定していません。ですから、`ManagedThreadId`を気にするべきではありません。 > > Beginメソッドの様に、何秒かおきに処理するという場合 > > より良いアプローチはBegin1とBegin2ではどちらですか? > > > 質問文のアプローチはどちらも処理時間に応じで次の実行開始が遅れます。それを防ごうと処理時間を測定したり行うと処理が膨れ上がります。 そうならないように最初からタイマーを使うべきです。タイマーであれば、スレッドスケジューラーと連動して、指定したタイミングで処理が起動されます。アプリケーションレベルで管理しないため効率的に動作します。