2013-04-16 1 views
5

データベースから製品を取得するタスクがあり、一部のUI変更を処理するアクションがContinueWithなので、タスクが新しいスレッドを作成し、UIの変更がUIスレッドで実行されなかったため問題が発生しました。TaskScheduler.CurrentとTaskScheduler.FromCurrentSynchronizationContext()の違いは?

私は、この修正プログラムを使用してみました:

var currentScheduler = TaskScheduler.Current; 

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

をそれがまったく機能しませんでした。私はチェックし、ContinueWithはcurrentSchedulerのスレッドではなく別のスレッドで実行されました。

私はこの方法を発見:

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

をし、それが動作します。違いは何ですか?なぜ私の最初のコードは動作しませんでしたか? ありがとう! TaskScheduler.Currentのドキュメントから

答えて

12

は、タスク内から呼び出されていない場合は、現在のデフォルトのスケジューラを返します。

が続いTask Schedulers documentationから:タスク並列ライブラリとPLINQのため

デフォルトのスケジューラキューと作業を実行するための.NET FrameworkのThreadPoolを使用しています。

タスクに参加していないときにTaskScheduler.Currentを使用すると、スレッドプールを使用するスケジューラが表示されます。

TaskScheduler.FromCurrentSynchronizationContext()に電話すると、現在のsynchronization contextのUIフォームまたはWPF(UIスレッドから呼び出された場合)が関連するUIスレッドでスケジュールされるコンテキストになります。

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

C#5とasync/awaitを使用できる場合は、すべてより簡単に処理されます。

+0

これは、UIコンポーネントのコンストラクタでasync/await likeを使用できない場合に便利です。 – Chin

+0

@Chin:私は特にそれを使用しません - 私は一般的に作業を行い、その後、高速なコンストラクタを呼び出す静的非同期メソッドを持っています。 –

+0

もう少し詳しく説明できますか?特に私は別の質問があります:http://stackoverflow.com/questions/31886276/handle-exception-when-using-task-run-in-ui-constructorそれはちょっと関連しています – Chin

関連する問題