首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >取消任务

取消任务
EN

Stack Overflow用户
提问于 2012-12-15 21:14:01
回答 3查看 839关注 0票数 6

我试着运行一个简单的示例,说明取消以下任务的情况。

代码语言:javascript
复制
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);

我原以为Console.WriteLine("Task 2 cancelled? {0}", task2.IsCanceled);会打印**"Task 2 cancelled? True"**,但它打印了"False"

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

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

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-12-15 22:34:13

首先,也许你误解了IsCanceled的意思?它并不意味着“这个Task正在等待取消,所以它应该很快完成”,它意味着“这个Task已经被取消了,它现在已经完成了”。

如果你没有误解这一点,那就想想事件的顺序到底是什么。所发生的事情是:

  1. ThrowIfCancellationRequested()被调用,但是令牌还没有被取消,所以它不会抛出。
  2. Thread.Sleep()被调用,因此运行Task的线程将休眠。
  3. Cancel()被称为。
  4. 检查IsCanceledTask中的代码没有机会意识到令牌已被取消,因此它仍在运行,因此IsCanceled返回false
  5. ThrowIfCancellationRequested()再次被调用,这一次它抛出,这实际上取消了Task

这就是为什么ISCanceledfalse返回给您的原因。如果希望它返回true,可以在检查IsCanceled之前添加类似Thread.Sleep(150)的内容,或者更好的是,实际上等待Task完成。

票数 5
EN

Stack Overflow用户

发布于 2012-12-15 21:20:48

任务在您要求取消之前结束,请看下面的内容,这可能有助于更好地了解如何解决您的问题

通过从这里读取http://social.msdn.microsoft.com/Forums/da-DK/parallelextensions/thread/9f88132a-f8bd-4885-ab63-645d7b6c2127,似乎可以在任务“真正”启动之前,而是在任务排队之后,使用令牌来取消任务。

它更多地是取消计划中的任务,但尚未启动的一种方式。一旦任务运行,取消它的唯一方法是通过您自己在方法中的检查进行协作。否则,您必须始终启动任务,然后在内部检查它,这将增加许多额外的、不必要的开销。

你甚至可以从Cancellation token in Task constructor: why?上读到它

票数 2
EN

Stack Overflow用户

发布于 2012-12-15 21:34:21

这不是回答,而是写在评论里的时间太长了

代码语言:javascript
复制
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);
  • 上面的代码输出了预期的内容,而且我从来没有得到'Task 2-Int值{0}‘的打印,所以我认为在取消之前它还没有完成。
  • 请注意,取消任务会在我的示例中引发异常。
  • 有一些patterns for handling exceptions using tasks可以很好地阅读。
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13896269

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档