2014-01-17 35 views
6

這是這個問題的延續: Multiple Task Continuation任務取消的異常(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); 

編輯:

我不取消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

多數民衆贊成在奇怪的事情,它不是。我解開了我的'cancellationToken.Cancel()',它仍然發生。 – Simon

+0

什麼是堆棧跟蹤?那麼Close()在這裏呢? – Heath

回答

8

你說SetCancelledHandler只是增加了任務的延續。我認爲這是RunAsync獲取作爲參數的相同任務,儘管我無法通過代碼告知SetCancelledHandler如何獲得繼續任務(我假設我們缺少一些代碼)。無論如何...

您在任務完成,取消並出現故障時將運行的任務註冊3個延續。現在讓我們假設原始任務成功完成而不被取消。這意味着你的兩個延續(OnCanceledOnFaulted)將不會運行,因爲它們不需要。告訴任務不在TPL中運行的方法是取消它,並自動發生。

你的2個代碼片段之間的區別在於你在第一個任務延續中的await,他們被取消,這解釋了你的異常。在第二個片段中,您不等待延續,只是成功完成的原始任務。

P.S:我認爲第二種選擇更合適。你不需要await所有這些延續。你想讓他們在需要時運行。

TL; DR:您await取消的繼續任務。繼續任務,而不是原來的,是引發異常的那個任務。

+1

這很有道理,謝謝 – Simon

+1

@Simon任何時候... – i3arnon