【问题标题】:Task Status when cancelled取消时的任务状态
【发布时间】:2012-08-26 11:58:36
【问题描述】:

我写了以下代码:

CancellationTokenSource tokenSource = new CancellationTokenSource();
CancellationToken token = tokenSource.Token;

int i = 0;
Console.WriteLine("Calling from Main Thread {0}", System.Threading.Thread.CurrentThread.ManagedThreadId);

Task t1 = new Task(() =>
{
    while (true)
    {
        try
        {
            token.ThrowIfCancellationRequested();
        }

        catch (OperationCanceledException)
        {
            Console.WriteLine("Task1 cancel detected");
            break;
        }

        Console.WriteLine("Task1: Printing: {1}", System.Threading.Thread.CurrentThread.ManagedThreadId, i++);
    }
}, token);

Task t2 = new Task(() =>
{
    while (true)
    {
        try
        {
            token.ThrowIfCancellationRequested();
        }

        catch (OperationCanceledException)
        {
            Console.WriteLine("Task2 cancel detected");
            break;
        }

        Console.WriteLine("Task2: Printing: {1}", System.Threading.Thread.CurrentThread.ManagedThreadId, i++);
    }
});

t1.Start();
t2.Start();
Thread.Sleep(100);
tokenSource.Cancel();

t1.Wait();//wait for thread to completes its execution
t2.Wait();//wait for thread to completes its execution
Console.WriteLine("Task1 Status:{0}", t1.Status);
Console.WriteLine("Task2 Status:{0}", t1.Status);

我在这里取消任务,然后状态也显示 RanToCompletion 但如果我删除两个任务的等待,那么它显示我取消状态...

当我取消任务时,无论如何我都期待取消状态......

编辑:来自 MSDN 通过抛出 OperationCanceledException 并将请求取消的令牌传递给它。执行此操作的首选方法是使用 ThrowIfCancellationRequested 方法。以这种方式取消的任务将转换为 Canceled 状态,调用代码可以使用该状态来验证任务是否响应了其取消请求。

如果您不使用 Wait 或 WaitAll 方法来等待任务,则任务只是将其状态设置为 Canceled。

【问题讨论】:

    标签: c# task-parallel-library


    【解决方案1】:

    当您捕获 OperationCanceledException 并跳出 while 循环时,任务将正常结束,任务状态将为 RanToCompletion。

    为了获得 Canceled 状态,您需要重新抛出 OperationCanceledException 或根本不捕获它。

    根据MSDN,任务状态将在以下情况下被取消:

    任务通过抛出一个 OperationCanceledException 带有自己的 CancellationToken 而 令牌处于信号状态,或者任务的 CancellationToken 是 在任务开始执行之前已经发出信号。更多 信息,请参阅Task Cancellation

    由于您在源代码中吞下了异常,因此任务状态将为 RanToCompletion。

    要回答您关于为什么取消等待时状态为已取消的问题,这可能是因为尚未捕获异常并且已在较早的时间检查了取消状态。 这种行为不应被认为是可靠和可重现的。

    【讨论】:

    • 感谢齐亚德。但是当我取消对任务的等待时,我得到了取消状态,这造成了一些混乱..
    • 更新了 MSDN 链接中的问题:仍然对我更新的语句感到困惑。和你最后的说法相矛盾吗?
    • @RaoBHavik 我认为当你等待时状态为 Canceled 的事实完全是巧合。事实上,如果你用 Thread.Sleep(5000) 替换这两个等待,任务状态可能会是 RanToCompletion。
    猜你喜欢
    • 2020-01-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-27
    • 1970-01-01
    相关资源
    最近更新 更多