我想在一定的毫秒後取消耗時的任務,對於我的情況,我認爲CancellationToken.Register方法最適合與其他方法進行持續輪詢或WaitHandle相比。 CancellationToken.Register方法將幫助我定義一個委託,在該委託中計劃將任務取消並停止任務的執行;這個委託將在任務被取消時被調用(根據我的目標某個毫秒後)。下面是測試代碼,我有我打算擴大爲多個任務,後來與嵌套任務:正確處理CancellationToken.Register的異常
List<Task> tasks = new List<Task>();
CancellationTokenSource tokenSource = new CancellationTokenSource();
CancellationToken cancellationToken = tokenSource.Token;
Task t1 = Task.Factory.StartNew(() =>
{
// check cancellation token before task begins
if (cancellationToken.IsCancellationRequested) cancellationToken.ThrowIfCancellationRequested();
// register a callback to handle cancellation token anytime it occurs
cancellationToken.Register(() =>
{
Console.WriteLine("Task t1 cancelled");
cancellationToken.ThrowIfCancellationRequested();
});
// simulating a massive task; note, it is not a repeating task
Thread.Sleep(12000);
}, cancellationToken);
tasks.Add(t1);
try
{
// cancel token after 3000 ms + wait for all tasks
tokenSource.CancelAfter(3000);
Task.WaitAll(tasks.ToArray());
// OR wait for all tasks for 3000 ms and then cancel token immediately
//Task.WaitAll(tasks.ToArray(), 3000);
//tokenSource.Cancel();
}
catch (AggregateException e)
{
Console.WriteLine("\nAggregateException thrown with the following inner exceptions:");
// Display information about each exception.
foreach (var v in e.InnerExceptions)
{
if (v is TaskCanceledException)
Console.WriteLine(" TaskCanceledException: Task {0}", ((TaskCanceledException)v).Task.Id);
else
Console.WriteLine(" Exception: {0}", v.GetType().Name);
}
Console.WriteLine();
}
finally
{
tokenSource.Dispose();
}
我,不過,裏面cancellationToken.Register回調方法的執行過程中面臨着異常處理的問題。對cancellationToken.ThrowIfCancellationRequested()的調用給我例外:「OperationCanceledException未被用戶代碼處理」,後面跟着「AggregateException was unhandled」。我已經閱讀了VS設置,取消了第一個OperationCanceledException異常的User-unhandled異常,但是我的應用程序在第二個AggregateException異常之後終止; Task.WaitAll的try..catch塊似乎沒有處理這個問題。
我試圖在一個try..catch塊中放置cancellationToken.ThrowIfCancellationRequested(),但這種方法的問題是該任務繼續執行剩餘的步驟,我不希望這樣做。我沒有看到這種輪詢方式的行爲。
// poll continuously to check for cancellation instead of Register
// but I do not want my massive task inside this repeating block
while (true)
{
if (cancellationToken.IsCancellationRequested)
{
Console.WriteLine("Task t1 Canceled.");
cancellationToken.ThrowIfCancellationRequested();
}
}
我在做什麼錯誤的CancellationToken.Register方法?