C# 任务的取消

C# 任务的取消,c#,.net,task-parallel-library,C#,.net,Task Parallel Library,我试着运行一个简单的取消任务的例子,如下所示 CancellationTokenSource tokenSource2 = new CancellationTokenSource(); CancellationToken token2 = tokenSource2.Token; Task task2 = new Task(() => { for (int i = 0; i < int.MaxValue; i++) { token2.ThrowIf

我试着运行一个简单的取消任务的例子,如下所示

CancellationTokenSource tokenSource2 = new CancellationTokenSource();

CancellationToken token2 = tokenSource2.Token;


Task task2 = new Task(() =>
{
    for (int i = 0; i < int.MaxValue; i++)
    {
        token2.ThrowIfCancellationRequested();
        Thread.Sleep(100);
        Console.WriteLine("Task 2 - Int value {0}", i);
    }
}, token2);

task2.Start();

Console.WriteLine("Press any key to cancel the task");
Console.ReadLine();

tokenSource2.Cancel();
Console.WriteLine("Task 2 cancelled? {0}", task2.IsCanceled);
CancellationTokenSource tokenSource2=新的CancellationTokenSource();
CancellationToken2=tokenSource2.Token;
任务task2=新任务(()=>
{
对于(int i=0;i
我期望
Console.WriteLine(“task2已取消?{0}”),task2.IsCanceled
将打印任务2已取消?True“***
,但它打印的是“False”

你知道发生了什么事吗?这是预期的行为吗?谢谢


编辑:确保在调用取消请求之前任务尚未完成。我添加了
Console.ReadLine()

任务在您请求取消之前结束,请查看下面的内容。这可能有助于进一步了解如何解决您的问题

从这里读取,似乎该令牌用于在任务“真正”启动之前取消任务,但在任务排队之后取消任务

这更像是一种取消已计划发生但尚未启动的任务的方法。一旦任务正在运行,取消它的唯一方法就是通过您自己在方法中的检查进行合作。如果没有这一点,您必须始终启动任务,然后在内部检查它,这将增加许多额外的、不必要的开销


你甚至可以从

中读到它。这不是一个答案,但太长了,不能写在评论中

CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
CancellationToken cancellationToken = cancellationTokenSource.Token;

Task task = new Task(() =>
{
    for (int i = 0; i < int.MaxValue; i++)
    {
        cancellationToken.ThrowIfCancellationRequested();
        Console.WriteLine("Task 2 - Int value {0}", i);
    }
}, cancellationToken);

task.Start();

cancellationTokenSource.Cancel();
try
{
    task.Wait();
}
catch (AggregateException ae)
{
    if(ae.InnerExceptions.Single() is TaskCanceledException)
        Console.WriteLine("Caught TaskCanceledException");
    else
        Console.WriteLine("Did not catch canceled");
}
Console.WriteLine("Task 2 cancelled? {0}", task.IsCanceled);
CancellationTokenSource CancellationTokenSource=新的CancellationTokenSource();
CancellationToken CancellationToken=cancellationTokenSource.Token;
任务=新任务(()=>
{
对于(int i=0;i
  • 上面的代码打印了预期的内容,我从来没有打印过'Task 2-Int value{0}',因此我认为在取消之前它不会完成
  • 请注意,取消任务会在我的示例中引发异常
  • 有一些是值得一读的

首先,可能您误解了被取消的
是什么意思?这并不意味着“此
任务
正在等待取消,因此应该很快完成”,而是意味着“此
任务
已取消,现在已完成”

如果你没有误解这一点,请思考事件的确切顺序。结果是:

  • 调用了
    throwifcancellationrequest()
    ,但令牌尚未取消,因此它不会抛出
  • 调用
    Thread.Sleep()
    ,因此运行
    任务的线程将休眠
  • 调用
    Cancel()
  • IsCanceled
    已选中。
    任务中的代码没有机会意识到令牌已被取消,因此它仍在运行,因此
    IsCanceled
    返回
    false
  • 再次调用
    throwifcancellationrequest()
    ,这次它抛出,实际上取消了
    任务
  • 这就是
    ISCanceled
    向您返回
    false
    的原因。如果您想让它返回
    true
    ,可以在选中
    IsCanceled
    之前添加类似
    Thread.Sleep(150)
    的内容,或者更好的是,实际等待
    任务完成