2012-02-17 30 views
7

いつTaskEx.Runを使用するのかを理解しようとしています。私は同じ結果を生成する以下に書いた2つのコードサンプルを提供しました。どのような私が見に失敗すると、私は正当な理由があると確信している、 Task.RunExTaskEx.RunExアプローチを取るだろうし、誰かが私を埋めることができ期待していた理由である。TaskEx.RunとTaskEx.RunExを使用する場合

async Task DoWork(CancellationToken cancelToken, IProgress<string> progress) 
{ 
    int i = 0; 
    TaskEx.RunEx(async() => 
     { 
      while (!cancelToken.IsCancellationRequested) 
      { 
       progress.Report(i++.ToString()); 
       await TaskEx.Delay(1, cancelToken); 
      } 
     }, cancelToken); 
} 
private void Button_Click(object sender, RoutedEventArgs e) 
{ 
    if (button.Content.ToString() == "Start") 
    { 
     button.Content = "Stop"; 
     cts.Dispose(); 
     cts = new CancellationTokenSource(); 
     listBox.Items.Clear(); 
     IProgress<string> progress = new Progress<string>(s => 
     { 
      listBox.Items.Add(s); 
      listBox.ScrollIntoView(listBox.Items[listBox.Items.Count - 1]); 
     }); 
     DoWork(cts.Token, progress); 
    } 
    else 
    { 
     button.Content = "Start"; 
     cts.Cancel(); 
    } 
} 

が、私は同じ結果を得ることができますのように

+0

上記のスレッドは、TaskEx.RunExの理由についての説明であり、CTPのコア.NET機能には反映されなかった変更点に関連していますが、最終リリースでは正しく統合されます。 –

+0

変更されたタスク.RunEx'から 'TaskEx.RunEx'へAsync CTP' Task'クラスには 'Run()'と 'RunEx()'もありません。それらは両方とも 'TaskEx'にあります。私が間違っていると私を訂正してください。 –

答えて

0

私が理解しているように、ほとんどのシナリオでTask.Runは新しいスレッドを生成します。

メソッドを非同期としてマークしてawaitersを使用するだけで、これは新しいスレッドが作成されていることを意味するわけではなく、呼び出されたSAMEの実行スレッドでスケジュールされます。多くの場合。

ここでのトリックはSchedulingContextと関係があります。マルチスレッドアパートメントに設定されている場合は、スレッドプール上の実行可能なスレッドに補完を委託します。 WPFとWinFormsのすべてのUIコードがシングルスレッドのアパートにある場合、コード内に目に見えるスレッドマーシャリングがなくてもUIで直接作業が完了できるように、呼び出し側のスレッドに戻ります。

+0

'Task.Run'はスレッドプールにキューイングします。スレッドプールは通常新しいスレッドを開始しません。 'await'は現在の' SynchronizationContext'または 'TaskScheduler'(スレッドではない)への継続をスケジュールします - [この記事の最後]を参照してください(http://msdn.microsoft.com/en-us/magazine/gg598924.aspx)これはCTP v3(およびVS11 dev preview)の時点でも適用されます。私は[私の非同期イントロポスト](http://nitoprograms.blogspot.com/2012/02/async-and-await.html)の非同期コンテキストもカバーしています。このコンテキストは、MTAまたはSTAとは関係ありませんが、STAまたはMTAをサポートするコンテキストを持つことは可能です。 –

+0

私は心地よく訂正しました:D – Firoso

11

スレッドプールコンテキストで同期コードを実行する場合は、TaskEx.Runを使用します。

スレッドプールコンテキストで非同期コードを実行する場合は、TaskEx.RunExを使用します。

スティーブンToubは、動作の違いに関連する2件のブログの記事があります。

これは、あなたがcreating tasksのために持っているいくつかの選択肢の一つです。 Run/RunExを使用する必要がない場合は、そうしないでください。単純なasyncメソッドを使用し、何かをバックグラウンドで実行する必要がある場合は、Run/RunExを使用してください。

+0

実際にはそうではありません... RunExはラムダ式を返す値と関係しています...非同期ではありません。ハンドルは、非同期ラムダはちょうどいいです。 – Firoso

+2

.Net 4.5 DPでは、 'Task.Run()'のみが存在し、 'Ex'は存在しないようです。 – svick

+4

TaskExはCTPのみです。 .Net 4.5ではTaskExのメソッドがTaskに統合されました。 – Phil

1

DoWork()の2つの方法の違いは、最初のもの(TaskEx.RunEx()を使用)が全く非同期ではないことです。それは完全に同期して実行され、別のスレッドで他のタスクを開始し、完了したTaskを直ちに返します。 await edまたはWait()がそのタスクで実行された場合、が内部タスクが完了するまで待機しません。

関連する問題