web-dev-qa-db-ja.com

UIスレッドでのタスクの継続

初期タスクの作成元のスレッドでタスクの継続を実行するように指定する「標準」の方法はありますか?

現在、私は以下のコードを持っています-それは動作していますが、ディスパッチャを追跡し、2番目のアクションを作成することは不要なオーバーヘッドのようです。

dispatcher = Dispatcher.CurrentDispatcher;
Task task = Task.Factory.StartNew(() =>
{
    DoLongRunningWork();
});

Task UITask= task.ContinueWith(() =>
{
    dispatcher.Invoke(new Action(() =>
    {
        this.TextBlock1.Text = "Complete"; 
    }
});
202
Greg Sansom

TaskScheduler.FromCurrentSynchronizationContext()で継続を呼び出します:

    Task UITask= task.ContinueWith(() =>
    {
     this.TextBlock1.Text = "Complete"; 
    }, TaskScheduler.FromCurrentSynchronizationContext());

これは、現在の実行コンテキストがUIスレッド上にある場合にのみ適しています。

326
Greg Sansom

非同期を使用すると、次のことができます。

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.
30
Johan Larsson

戻り値がある場合、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());
20
Simon_Weaver

これは非常に便利なスレッドであり、非常にシンプルな実装だと思うので、このバージョンを追加したかっただけです。マルチスレッドアプリケーションの場合、さまざまなタイプでこれを複数回使用しました。

 Task.Factory.StartNew(() =>
      {
        DoLongRunningWork();
        Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() =>
              { txt.Text = "Complete"; }));
      });
11
Dean