2014-01-16 95 views
1

我想了解這種情況下更清楚一點:多任務延續

考慮下面的代碼:

frmProgressAsync prog = new frmProgressAsync(true); 
TaskWithProgress t = new TaskWithProgress("Smoothing CP", true); 
t.Task = A.ShowMovingAverage(tension,t.Progress) 
     .ContinueWith(prev => 
      { 
       t.ProgressInformation.Report("Smoothing FG"); 
       B.ShowMovingAverage(tension, t.Progress); 
      }); 
await prog.RunAsync(t); 

我有兩個任務,我希望運行A.ShowMovingAverageB.ShowMovingAverage。兩個都返回一個Task。

prog.RunAsync()方法,我有以下幾點:

public virtual Task RunAsync(TaskWithProgress task) 
    { 
     Show(); 
     TaskIsRunning(); 
     task.ContinueWith(Close(), CancellationToken.None, TaskContinuationOptions.OnlyOnRanToCompletion, this._Scheduler); 
     return task.Task; 
    } 

那麼有效,我有三個任務,又一個以前完成後運行。

現在我的問題是在某些情況下,第一項任務幾乎立即完成。當致電prog.RunAsync(),並且最後的延續被追加到任務中時,它立即運行,關閉表格。

我可以看到,如果我在最後的ContinueWith()呼叫中斷,任務狀態爲RanToCompletion,但我期待繼續將其重置爲正在進行中。

請問有人可以更乾淨地解釋這種行爲?並提供一個可能的解決方案,使所有的任務(續集)在最後的繼續之前完成?

回答

3

任務只完成一次。附加延續時,您將創建一個新任務,該任務在前期任務完成時啓動。所以,我相信你看到的問題是RunAsync附加Close延續,但沒有對延續任務做任何事情;考慮task.Task = task.ContinueWith(Close(), ...)

但是,我建議您使用await而不是ContinueWith。我發現通常會澄清代碼並使其更易於理解。

frmProgressAsync prog = new frmProgressAsync(true); 
TaskWithProgress t = new TaskWithProgress("Smoothing CP", true); 
t.Task = ShowMovingAveragesAsync(A, B, tension, t.Progress); 
await prog.RunAsync(t); 

private async Task ShowMovingAveragesAsync(TA A, TA B, TT tession, IProgress<string> progress) 
{ 
    progress.Report("Smoothing FG"); 
    await A.ShowMovingAverageAsync(tension, progress); 
    progress.Report("Smoothing FG"); 
    await B.ShowMovingAverageAsync(tension, progress); 
} 

public virtual async Task RunAsync(TaskWithProgress task) 
{ 
    Show(); 
    TaskIsRunning(); 
    await task; 
    Close(); 
} 
+1

謝謝斯蒂芬,我注意到在這兩種方法中,您將返回類型定義爲「任務」,但實際上並不返回任何內容。這與你在博客中勸阻的'async void'不一樣嗎? – Simon

+1

否; 'async Task'是定義一個沒有返回值的'async'方法的正確方法。它沒有任何'async void'引起的問題。 –

+0

非常感謝您的幫助 – Simon