2

ダイアログを表示したい場合、 で例外を取得し、task1そのダイアログから新しい を開始するメソッドを呼び出しますtask2。問題は、実行中にオーナー ウィンドウがフリーズすることtask2です。

簡単なコードを見てください ( Task Parallel Library uses):

private void button1_Click(object sender, RoutedEventArgs e)
{   
    var scheduler = TaskScheduler.FromCurrentSynchronizationContext();
    Task.Factory.StartNew
      (() => SomeHardMethod(1)).ContinueWith(TaskContinuation, scheduler);
}
private void TaskContinuation(Task parentTask)
{   
    if (parentTask.IsFaulted)
    {
        // If we get an exception - show a dialog that starts a new task
        var dlg = new WindowDialog();  
        var scheduler = TaskScheduler.FromCurrentSynchronizationContext();
        if (dlg.Show())
        {   
          //Here we start a new task
           Task.Factory.StartNew
             (() => SomeHardMethod(2)).ContinueWith(TaskContinuation, scheduler);
        }
        var ex = parentTask.Exception;
    }
}
private void SomeHardMethod(int mode)
{   
    if (mode == 1)
    {    
         throw new ArgumentException("mode");
    }
    else
    {   //Any long operation...
        Thread.Sleep(3000);
    }    
}

私にとっては、最初にbutton1_Clickメソッドでタスクを開始するとUIでは実行されず、次に新しいタスクを開始するとUIスレッドで実行されるため、所有者ウィンドウがフリーズするのは奇妙です。

コードのこの部分が実際にバックグラウンドではなくタスクを開始する理由を誰かが明確にすることができますか?

if (dlg.Show())
{
    //Here we start a new task
    Task.Factory.StartNew
      (() => SomeHardMethod(2)).ContinueWith(TaskContinuation, scheduler);
}
4

1 に答える 1

3

Taskusingを開始するTask.Factory.StartNew()と、現在のスケジューラが使用されます。これが意味することは、UI スレッドで実行さTaskれる から this wayを開始Taskすると、UI スレッドでも実行されるということです。Taskただし、UI スレッドからa を開始する場合、同じことは発生しませんが、 Task(イベント ハンドラーのように) 外部から開始します。

がバックグラウンド スレッドで確実にTask実行されるようにするには、 を使用することを明示的に指定する必要がありますTaskScheduler.Default

于 2013-05-11T13:34:04.350 に答える