昨天我剛剛介紹了任務(TPL),因此我試着做一個小樣本項目以瞭解如何使用它們。任務取消和TaskContinuationOptions
我的示例項目設置了一個開始按鈕,開始遞增進度條。第二個按鈕取消任務。一個文本框,用於報告何時使用TaskContinuationOptions.OnlyOnRanToCompletion進行的延續以及用於報告何時使用TaskContinuationOptions.OnlyOnCanceled進行延續的文本框。
我可以創建並執行一個任務,但取消它的方式可以讓TaskContinuationOptions.OnlyOnCanceled標誌繼續觸發,這是一個問題。
我創建的任務如下:
private void StartTask()
{
CancellationTokenSource tokenSource = new CancellationTokenSource();
CancellationToken token = tokenSource.Token;
Task task = null;
task = Task.Factory.StartNew(() => DoWork(tokenSource), tokenSource.Token);
//A list<CancellationTokenSource> so that I can cancel the task when clicking a button on the UI Thread.
MyTasks.Add(tokenSource);
Task completed = task.ContinueWith(result => TaskCompleted(), TaskContinuationOptions.OnlyOnRanToCompletion);
Task canceled = task.ContinueWith(result => TaskCanceled(), TaskContinuationOptions.OnlyOnCanceled);
}
我取消任務如下:
private void CancelTasks()
{
foreach (CancellationTokenSource tokenSource in MyTasks)
{
tokenSource.Cancel();
}
}
我的工人功能如下:
private void DoWork(CancellationTokenSource tokenSource)
{
if (progressBar1.InvokeRequired)
{
progressBar1.Invoke(new Action(() => DoWork(tokenSource)));
return;
}
try
{
bool dowork = true;
while (dowork)
{
tokenSource.Token.ThrowIfCancellationRequested();
if (progressBar1.Value == progressBar1.Maximum)
{
dowork = false;
}
Thread.Sleep(1000);
progressBar1.PerformStep();
Application.DoEvents();
}
countCompleted++;
}
catch (OperationCanceledException)
{
}
}
在其他職位,我已閱讀,它已被建議tokenSource.Token.ThrowIfCancellationRequested()是什麼設置條件評估由TaskContinuationOptions.OnlyOnCanceled編輯。
無的我所看到的實施例包括使用的:
catch (OperationCanceledException)
{
}
然而,如果沒有它的程序停止時,我調用tokenSource.Cancel();
就目前而言,當我調用tokenSource.Cancel()時,將繼續使用TaskContinuationOptions.OnlyOnRanToCompletion運行,而不是TaskContinuationOptions.OnlyOnCanceled。
很明顯,我沒有正確地做到這一點。
編輯:
做一些進一步的閱讀中,我發現,規定的評價是:
「趕上(OperationCanceledException){}將設置爲RanToCompletion任務狀態,而不是取消」
因此刪除catch(OperationCanceledException){}允許將任務的狀態設置爲取消,但是程序在tokenSource.Token.ThrowIfCancellationRequested()中斷。但是如果我繼續完成中斷,那麼運行TaskContinuationOptions.OnlyOnCanceled的延續任務會很好。
但我該如何調用tokenSource.Token.ThrowIfCancellationRequested()而不允許程序中斷,同時允許將任務狀態設置爲取消?
而不是調用ThrowIfCancellationRequested(),檢查IsCancellationRequested屬性並打破循環? – Jon 2013-03-25 01:41:12
@Jon當我嘗試這樣做時,它確實允許我跳出循環,但任務的狀態將返回爲RanToCompletion,而不是取消,因此會調用錯誤的延續。 – Blau 2013-03-25 01:54:29
好吧,我發現另一個帖子,有人遇到類似的問題;他們表示他們意識到他們正在以調試模式啓動該程序,並且在未經調試的情況下運行該程序時就能正常工作。所以我嘗試了這一點,並且一切看起來都正常。但是這意味着我不能在調試模式下運行而不必處理這個拋出的異常。有沒有辦法在調試模式下運行時正常工作? – Blau 2013-03-25 03:01:47