任务状态值是故障而是取消

时间:2016-02-23 13:22:02

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

我需要调用我的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);

我的控制台输出如下:

enter image description here

这是我期望并为我工作的。如果我复制任务中的代码并创建一个方法,我不再将任务状态设置为已取消。我的状态为Faulted。我必须知道操作是否被取消或者在阅读过程中是否发生了异常。我无法弄清楚为什么我没有在这里取消任务状态。

    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();
    }
}

enter image description here

1 个答案:

答案 0 :(得分:2)

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

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

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

来自MSDN

  

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

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