【问题标题】:Task Status Value is Faulted instead Cancelled任务状态值是故障而不是已取消
【发布时间】:2016-02-23 13:22:01
【问题描述】:

我需要调用我的 Task 对象的一个​​方法。我的任务执行某种读取,如果完成时间超过 2 秒,我将取消该操作。

我有这个代码作为模拟:

    var cts = new CancellationTokenSource(TimeSpan.FromMilliseconds(2000));

    var task = Task.Run(() =>
    {
        try
        {
            int i = 0;

            while (true)
            {
                Thread.Sleep(500);

                cts.Token.ThrowIfCancellationRequested();

                Console.WriteLine("i = {0}", i);
                i++;

                if (i > 3) throw new InvalidOperationException();
            }
        }
        catch (Exception e)
        {
            Console.WriteLine("Exception {0}", e.Message);
            throw;
        }
    });

    task.ContinueWith(t => Console.WriteLine(t.Status), TaskContinuationOptions.NotOnRanToCompletion);

我的控制台输出如下:

这是我所期望的并且对我有用。如果我复制任务内的代码并创建一个方法,我不再将任务状态设为已取消。我的状态为故障。我必须知道操作是否被取消或读取过程中发生异常。我无法弄清楚为什么我没有在此处获得“已取消”的任务状态。

    var cts = new CancellationTokenSource(TimeSpan.FromMilliseconds(2000));

    var task = Task.Run(() =>
    {
        try
        {
            Tester(cts);
        }
        catch (Exception e)
        {
            Console.WriteLine("Exception {0}", e.Message);
            throw;
        }
    });

private static void Tester(CancellationTokenSource cts)
{
    int i = 0;

    while (true)
    {
        Thread.Sleep(500);

        cts.Token.ThrowIfCancellationRequested();

        Console.WriteLine("i = {0}", i);
        i++;

        if (i > 3) throw new InvalidOperationException();
    }
}

【问题讨论】:

    标签: c# c#-4.0 task-parallel-library


    【解决方案1】:

    如果您将令牌传递给Task.Run,您将获得预期的Canceled 结果:

    var task = Task.Run(() =>
    {
        try
        {
            Tester(cts);
        }
        catch (Exception e)
        {
            Console.WriteLine("Exception {0}", e.Message);
            throw;
        }
    }, cts.Token);
    

    任务需要知道哪个令牌会抛出OperationCanceledException - 只有来自正确来源的异常才会取消任务,所有其他异常都会出错。

    来自MSDN

    当任务实例观察到用户代码抛出的 OperationCanceledException 时,它会将异常的标记与其关联的标记(传递给创建任务的 API 的标记)进行比较。如果它们相同并且令牌的 IsCancellationRequested 属性返回 true,则任务将此解释为确认取消并转换到 Canceled 状态。

    我不完全明白你为什么首先得到Canceled 结果,看起来它与CancellationTokenSource 被捕获的时间有关。

    【讨论】:

    • 前段时间我花了一些时间才找到同样的原因。是的,传递令牌解决了这个问题。谢谢你的回答。
    猜你喜欢
    • 2020-01-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-28
    • 2014-06-27
    相关资源
    最近更新 更多