ContinueWithでTaskScheduler.FromCurrentSynchronizationContextを設定する必要があります。そうしないと、UIコンテキストで実行されません。これは、ContinueWithへのこの呼び出しに使用する必要があるオーバーライドに関するMSDNです。
最終的には次のようになります。
.ContinueWith(UpdateLabel, null,
TaskContinuationOptions.OnlyOnRanToCompletion,
TaskScheduler.FromCurrentSynchronizationContext());
何も起こっていないように見えるかもしれませんが、TPLは現在クロススレッド例外を飲み込んでいます。各結果を検査したり、その例外をチェックしたりしない場合は、おそらくUnobservedTaskExceptionを使用する必要があります。そうしないと、ガベージコレクションが発生すると、例外が発生します...デバッグが困難なエラーが発生する可能性があります。
アップデート
バックグラウンドワーカーによってセットアップおよび開始されるメインタスクに関する更新に基づいて、私の主な質問は、なぜこれがタスクを使用して開始できなかったのかということです。実際、にそれ以上ない場合Method
、これは実際には単なる二重の作業であり、他の開発者を混乱させる可能性があります。すでに非同期で開始されているので、backgroundworker内で作業を行い、 OnCompleteメソッドを使用してみませんかUpdateLabel
(バックグラウンドワーカーはすでにコンテキストを認識しているため)。
ただし、主な問題は同じです。したがって、TPLを使用する必要があると思われる場合は、他の解決策をいくつか示します。
Invoke
UpdateLabelメソッド内でメインUIスレッドに戻ることができます
- 現在のコンテキストをbackgroundworkerに渡し、代わりにそれを使用できます
Wait
元のタスクに戻ってから、ワーカーのoncompleteイベントを使用してラベルを更新できます。
これが私がこれを行う方法です(すべての擬似コード)
バックグラウンドワーカーメソッド:
Method() called because of Background worker
private void Method()
{
fileProcessor.ProcessEachMachine(mdetail);
}
Wire up background worker's OnRunWorkerCompleted:
if(!e.Cancelled && !e.Error)
UpdateLabel();
タスクのみの方法
Call Method() from the main thread and just let the TPL do its work :)
Task.Factory.StartNew(() => fileProcessor.ProcessEachMachine(mdetail))
.ContinueWith((precedingTask)=>{if(!precedingTask.Error)UpdateLabel;},
null, TaskContinuationOptions.OnlyOnRanToCompletion,
TaskScheduler.FromCurrentSynchronizationContext());