2014-01-16 2 views
1

Я хотел бы понять этот сценарий немного понятнее:Multiple Задача Продолжение

Рассмотрим следующий код:

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.ShowMovingAverage и B.ShowMovingAverage. Оба возвращают задачу.

В методе 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

Смежные вопросы