2014-01-17 2 views
6

Это продолжение от этого вопроса: Multiple Task ContinuationЗадача Отменено Exception (ThrowForNonSuccess)

Я изменил код, как в ответ, однако теперь я получаю TaskCancelledExceptions при попытке выполнения задач.

public virtual async Task RunAsync(TaskWithProgress task) 
{ 
    Show(); 
    TaskIsRunning(); 
    await SetCompletedHandler(TaskComplete()); 
    await SetCancelledHandler(TaskCancelled()) 
    await SetFaultedHandler(TaskFaulted()); 
    await task; 
    Close(); 
} 

однако следующий код не является. Я немного зациклен на том, почему.

public virtual Task RunAsync(TaskWithProgress task) 
{ 
    Show(); 
    TaskIsRunning(); 
    SetCompletedHandler(TaskComplete()); 
    SetCancelledHandler(TaskCancelled()) 
    SetFaultedHandler(TaskFaulted()); 
    return task; 
} 

Вызывающий код в основном включает в себя следующее:

await progressDialog.RunAsync(task); 

Edit:

Я не отменить cancellationtoken в любом месте, так что я не могу понять, почему это бросает это исключение.

Методы три SetXXXHandler() в основном выполняет следующий код с различным статусом продолжения:

task.ContinueWith(_ => action(), CancellationToken.None, TaskContinuationOptions.OnlyOnCanceled, this.Scheduler); 

Стек след здесь:

at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) 
    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) 
    at System.Runtime.CompilerServices.TaskAwaiter.GetResult() 
    at FugroDXExt.frmBaseProgressAsync.<RunAsync>d__7.MoveNext() in d:\C#\FugroDXExt\trunk\frmBaseProgressAsync.cs:line 92 
--- End of stack trace from previous location where exception was thrown --- 
    at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() 
    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) 
    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) 
    at System.Runtime.CompilerServices.TaskAwaiter.GetResult() 
    at FCP.Forms.frmProcessing.<mnuApplyCenteredSmoothing_ItemClick>d__34.MoveNext() in d:\C#\FCP\FCP\Forms\frmProcessing.cs:line 578 

Close() просто закрывает форму. Если я удалю эту линию, произойдет то же самое.

+0

Скорее всего, какой-то код где-то отменяет 'CancellationToken'. –

+0

Это странная вещь, ее нет. Я отвязал мой «cancelationToken.Cancel()», и он все еще встречается. – Simon

+0

Что такое трассировка стека? И что здесь делает Close()? – Heath

ответ

8

Вы говорите, что SetCancelledHandler просто добавляет продолжение к задаче. Я предполагаю, что та же самая задача RunAsync получает как параметр, хотя я не могу сказать по вашему коду, как SetCancelledHandler получает задачу для продолжения (я предполагаю, что нам не хватает кода). Anyways ...

Вы регистрируете 3 продолжения задачи, которая будет выполняться при завершении задачи, отменяется и сбой. Теперь давайте предположим, что первоначальная задача завершилась успешно, без отмены. Это означает, что 2 ваших продолжения (OnCanceled и OnFaulted) не будут работать, потому что им не обязательно быть. Способ сообщить задачу не запускать в TPL - это отменить ее, и это произойдет автоматически.

Разница между двумя фрагментами кода заключается в том, что в первом случае вы выполняете задачи, и они отменяются, что объясняет ваше исключение. Во втором фрагменте вы не ожидаете продолжения, просто первоначальная задача, которая успешно завершилась.

P.S: Я думаю, что второй вариант более уместен. Вам не нужно await все эти продолжения. Вы хотите, чтобы они запускались, если им нужно.

TL; Вы: await аннулирование задачи продолжения. Задача продолжения, а не оригинал, - это исключение.

+1

Это имеет смысл, спасибо – Simon

+1

@Simon В любое время ... – i3arnon

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