当我阅读文档时,CancellationTokenSource.Cancel 不应该引发异常。
CancellationTokenSource.Cancel
下面是对 cts.Cancel() 的调用;导致(不抛出)OperationCanceledException。
我对此非常有信心,就好像我注释掉了那一行然后最后一个 OperationCanceledException 不会被抛出。
随着 cts.Cancel 行处于活动状态,抛出异常的行是 t2.Wait(token);
如果我有延迟 cts.Cancel(); 然后 t2.Wait(token); 调用该行时不会立即抛出异常。
t2.Wait(令牌);仅在运行 cts.Cancel() 时引发该异常。
这是正确的行为吗?
如果它是一致的,那么我可以忍受它,但我不希望 cts.Cancel 导致异常。
我显然很困惑——我只是想了解这种行为,这样我就可以放心地将它带到生产环境中。
现在我正在使用 BackGroundWorker 执行此操作,我认为我可以使用等待和取消更轻松地跟踪和维护。
if (token.IsCancellationRequested || ctr == 100000000)
仍然抛出 ctr == 100000000
我仍然看到内部 OperationCanceledException 被捕获并且外部(较低)根本没有被抛出。
这段代码有问题吗?
或者它应该如何工作?
如果没有 Task t2 = Task.Run 中的 try catch,我会抛出未捕获的异常。
我认为这会被 t2.Wait 上的 try catch 捕获,但一次只有一个问题。
这是 .NET 4.5 上的控制台应用程序。
static void Main(string[] args)
{
CancellationTokenSource cts = new CancellationTokenSource();
CancellationToken token = cts.Token;
Task.Run(() =>
{
Thread.Sleep(1000);
cts.Cancel(); // this is thowing an exception that is caught on the last catch (OperationCanceledException Ex)
// according to the documentation this is not supposed
// if I comment out the cts.Cancel(); then the exeption is not thrown
if (token.IsCancellationRequested)
Console.WriteLine("Cancellation requested in Task {0}.",
Task.CurrentId);
else
Console.WriteLine("Cancellation Not requested in Task {0}.",
Task.CurrentId);
}, token);
//tried this but did not help
//Task.Run(() =>
//{
// //Thread.Sleep(1000);
// if (token.IsCancellationRequested)
// Console.WriteLine("Cancellation requested in Task {0}.",
// Task.CurrentId);
//}, token);
//Thread.Sleep(1000);
////cts.Cancel();
Task t2 = Task.Run(() =>
{
try
{
Console.WriteLine("Task t2 started Int32.MaxValue = " + Int32.MaxValue.ToString());
Thread.Sleep(4000);
for (int ctr = 0; ctr < Int32.MaxValue; ctr++)
{
if (ctr < 100 || ctr % 100000000 == 0)
{
Console.WriteLine(ctr.ToString());
}
if (token.IsCancellationRequested || ctr == 100000000) // || ctr == 100000000
{
Console.WriteLine("ThrowIfCancellationRequested in t2 Task {0}.",
Task.CurrentId);
throw new OperationCanceledException(token);
//token.ThrowIfCancellationRequested();
}
}
Console.WriteLine("Task {0} finished.",
Task.CurrentId);
}
catch (OperationCanceledException Ex)
{
//Console.WriteLine(Ex.ToString());
Console.WriteLine("OperationCanceledException in Task t2 {0}: The operation was cancelled.",
Task.CurrentId);
}
catch (Exception Ex)
{
Console.WriteLine("Task t2 = Task.Run Exception Ex" + Ex.Message);
}
});
try
{
Console.WriteLine("t2.Wait a");
t2.Wait(token);
}
catch (AggregateException e)
{
Console.WriteLine("AggregateException");
foreach (var v in e.InnerExceptions)
Console.WriteLine(e.Message + " " + v.Message);
}
catch (OperationCanceledException Ex)
{
//Console.WriteLine(Ex.ToString());
Console.WriteLine("OperationCanceledException in Task {0}: The operation was cancelled.",
t2.Id);
}
catch (Exception Ex)
{
Console.WriteLine(Ex.ToString());
}
Console.WriteLine("end");
Console.ReadLine();
}