我想在一定的毫秒后取消耗时的任务,对于我的情况,我认为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方法?