[英]Calling CancellationTokenSource.Cancel() within a task does not set Task.IsCanceled to true
[英]Why is Task.IsCanceled Not True?
我这里有一个简单的程序
private static void CancellingSingleTask()
{
DateTime whenStarted = DateTime.Now;
Console.WriteLine("[{0}] - Main: Started", TimeSpan.FromTicks(DateTime.Now.Ticks - whenStarted.Ticks));
CancellationTokenSource cts = new CancellationTokenSource();
CancellationToken ct = cts.Token;
Task task = Task.Factory.StartNew(() =>
{
int? taskId = Task.CurrentId;
Console.WriteLine("[{0}] - Task - [{1}]: Started", TimeSpan.FromTicks(DateTime.Now.Ticks - whenStarted.Ticks), taskId);
Thread.Sleep(2000);
if (ct.IsCancellationRequested)
{
Console.WriteLine("[{0}] - Task - [{1}]: Cancellation Requested", TimeSpan.FromTicks(DateTime.Now.Ticks - whenStarted.Ticks), taskId);
throw new OperationCanceledException();
}
Console.WriteLine("[{0}] - Task - [{1}]: No Cancellation Requested", TimeSpan.FromTicks(DateTime.Now.Ticks - whenStarted.Ticks), taskId);
}, ct);
Action Print = () =>
{
Console.WriteLine("[{0}] - Main: Task.IsCanceled = [{1}] Task.IsFaulted = [{2}] Task.IsCompleted = [{3}] Task.Status = [{4}]", TimeSpan.FromTicks(DateTime.Now.Ticks - whenStarted.Ticks),
task.IsCanceled, task.IsFaulted, task.IsCompleted, task.Status);
};
Console.WriteLine("[{0}] - Main: Started New Task", TimeSpan.FromTicks(DateTime.Now.Ticks - whenStarted.Ticks));
Print();
Thread.Sleep(1000);
Console.WriteLine("[{0}] - Main: Cancelling Task", TimeSpan.FromTicks(DateTime.Now.Ticks - whenStarted.Ticks));
cts.Cancel();
Thread.Sleep(2000);
Console.WriteLine("[{0}] - Main: After Cancelling Task", TimeSpan.FromTicks(DateTime.Now.Ticks - whenStarted.Ticks));
Print();
try
{
Console.WriteLine("[{0}] - Main: Waiting For Task", TimeSpan.FromTicks(DateTime.Now.Ticks - whenStarted.Ticks));
task.Wait();
Console.WriteLine("[{0}] - Main: After Waiting For Task", TimeSpan.FromTicks(DateTime.Now.Ticks - whenStarted.Ticks));
Print();
}
catch (AggregateException aggregateException)
{
Thread.Sleep(2000);
Console.WriteLine("[{0}] - Main: In Catch Block", TimeSpan.FromTicks(DateTime.Now.Ticks - whenStarted.Ticks));
Print();
foreach (var exception in aggregateException.InnerExceptions)
{
Console.WriteLine("[{0}] - Main: Received Exception In Task [{1}]", TimeSpan.FromTicks(DateTime.Now.Ticks - whenStarted.Ticks), exception.Message);
}
}
}
样本输出
[00:00:00.0010000]-主程序:已启动
[00:00:00.0040002]-主要:已开始新任务
[00:00:00.0060003]-Main:IsCanceled = [False] IsFaulted = [False] IsCompleted = [False]状态= [Running]
[00:00:00.0070004]-任务-[1]:已开始
[00:00:01.0070576]-主程序:取消任务
[00:00:02.0071148]-任务-[1]:请求取消
[00:00:03.0111722]-主程序:取消任务后
[00:00:03.0111722]-Main:IsCanceled = [False] IsFaulted = [True] IsCompleted = [True] Status = [Faulted]
[00:00:03.0111722]-主程序:等待任务
[00:00:05.0112866]-主要:在接球区
[00:00:05.0112866]-Main:IsCanceled = [False] IsFaulted = [True] IsCompleted = [True] Status = [Faulted]
[00:00:05.0112866]-主操作:任务中收到异常[操作已取消。
我从没看到Task.IsCanceled设置为true,是我犯了一个错误还是遗漏了一些明显的东西。 我已经对此问题进行了一些研究/搜索,但是找不到最终的答案。
注意:有关StackOverFlow的相关问题取消任务 任务IsCanceled为false,而我取消了 Task.IsCancelled则不起作用
我想您应该将CancellationToken
传递给OperationCanceledException
的构造函数。
if (ct.IsCancellationRequested)
{
Console.WriteLine("[{0}] - Task - [{1}]: Cancellation Requested", TimeSpan.FromTicks(DateTime.Now.Ticks - whenStarted.Ticks), taskId);
throw new OperationCanceledException(ct);
}
TPL将检查两个CancellationToken
是否相同,如果是这样,它将在您的情况下将其标记为“ Cancelled
,因此TPL假定您的任务未取消。
甚至更好地使用ThrowIfCancellationRequested
方法,就像那样简单
ct.ThrowIfCancellationRequested();
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.