初期タスクの作成元のスレッドでタスクの継続を実行するように指定する「標準」の方法はありますか?
現在、私は以下のコードを持っています-それは動作していますが、ディスパッチャを追跡し、2番目のアクションを作成することは不要なオーバーヘッドのようです。
dispatcher = Dispatcher.CurrentDispatcher;
Task task = Task.Factory.StartNew(() =>
{
DoLongRunningWork();
});
Task UITask= task.ContinueWith(() =>
{
dispatcher.Invoke(new Action(() =>
{
this.TextBlock1.Text = "Complete";
}
});
TaskScheduler.FromCurrentSynchronizationContext()
で継続を呼び出します:
Task UITask= task.ContinueWith(() =>
{
this.TextBlock1.Text = "Complete";
}, TaskScheduler.FromCurrentSynchronizationContext());
これは、現在の実行コンテキストがUIスレッド上にある場合にのみ適しています。
非同期を使用すると、次のことができます。
await Task.Run(() => do some stuff);
// continue doing stuff on the same context as before.
// while it is the default it is Nice to be explicit about it with:
await Task.Run(() => do some stuff).ConfigureAwait(true);
しかしながら:
await Task.Run(() => do some stuff).ConfigureAwait(false);
// continue doing stuff on the same thread as the task finished on.
戻り値がある場合、UIに送信する必要があります。次のような汎用バージョンを使用できます。
私の場合、これはMVVM ViewModelから呼び出されています。
var updateManifest = Task<ShippingManifest>.Run(() =>
{
Thread.Sleep(5000); // prove it's really working!
// GenerateManifest calls service and returns 'ShippingManifest' object
return GenerateManifest();
})
.ContinueWith(manifest =>
{
// MVVM property
this.ShippingManifest = manifest.Result;
// or if you are not using MVVM...
// txtShippingManifest.Text = manifest.Result.ToString();
System.Diagnostics.Debug.WriteLine("UI manifest updated - " + DateTime.Now);
}, TaskScheduler.FromCurrentSynchronizationContext());
これは非常に便利なスレッドであり、非常にシンプルな実装だと思うので、このバージョンを追加したかっただけです。マルチスレッドアプリケーションの場合、さまざまなタイプでこれを複数回使用しました。
Task.Factory.StartNew(() =>
{
DoLongRunningWork();
Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() =>
{ txt.Text = "Complete"; }));
});