11

データベースから製品を取得するタスクと、ContinueWithUI の変更を操作するアクションがあるため、タスクが新しいスレッドを作成し、UI の変更が UI スレッドではなく実行されたため、問題が発生しました。

私はこの修正を使用しようとしました:

var currentScheduler = TaskScheduler.Current;

Task.Factory.StartNew(() =>
{    
    // get products   
}).ContinueWith((x) => handleProductsArrived(x.Result, x.Exception), currentScheduler);

しかし、まったく機能しませんでした。チェックすると、ContinueWithcurrentScheduler のスレッドではなく、別のスレッドで実行されました。

私はこの方法を発見しました:

Task.Factory.StartNew(() =>
{
    // get products
}).ContinueWith((x) => handleProductsArrived(x.Result, x.Exception), TaskScheduler.FromCurrentSynchronizationContext());

そしてそれは動作します。違いは何ですか?最初のコードが機能しなかったのはなぜですか? ありがとう!

4

1 に答える 1

21

のドキュメントからTaskScheduler.Current

タスク内から呼び出されない場合、Current は Default スケジューラを返します。

次に、タスクスケジューラのドキュメントから:

Task Parallel Library と PLINQ の既定のスケジューラは、.NET Framework ThreadPool を使用して作業をキューに入れ、実行します。

したがってTaskScheduler.Current、タスクを実行していないときに使用すると、スレッド プールを使用するスケジューラが得られます。

を呼び出すとTaskScheduler.FromCurrentSynchronizationContext()、現在の同期コンテキストの 1 つが取得されます。これは、Windows フォームまたは WPF (UI スレッドから呼び出された場合) では、関連する UI スレッドでの作業をスケジュールするコンテキストです。

そのため、最初のコードは機能しませんでした。スレッド プール スレッドで継続を実行しました。2 番目のコードは、UI スレッドで継続を実行しました。

C# 5 と async/await を使用できる場合、これらすべてがはるかに簡単に処理されることに注意してください。

于 2013-04-16T08:29:43.220 に答える