【问题标题】:Canceled task also appears as completed取消的任务也显示为已完成
【发布时间】:2015-02-18 11:13:36
【问题描述】:

我正在玩异步等待和取消,以便对此事有更多了解。为此,我制作了以下控制台应用程序:

using System;
using System.Threading;
using System.Threading.Tasks;

namespace AsyncTest
{
    class Program
    {
        private static CancellationTokenSource _cancellationTokenSource;
        private static CancellationToken _cancellationToken;

        static void Main(string[] args)
        {
            Console.CancelKeyPress += myHandler;

            _cancellationTokenSource = new CancellationTokenSource();
            _cancellationToken = _cancellationTokenSource.Token;

            var task = DoWorkAsync(_cancellationToken).ContinueWith(ContinueMethod);
            task.Wait();

            Console.ReadLine();
        }

        protected static void myHandler(object sender, ConsoleCancelEventArgs args)
        {
            if (_cancellationToken.CanBeCanceled)
            {
                _cancellationTokenSource.Cancel();
            }
            args.Cancel = true;
        }

        static void ContinueMethod(Task task)
        {
            if (task.IsCanceled)
            {
                Console.WriteLine("The task was canceled");
            }

            if (task.IsCompleted)
            {
                Console.WriteLine("The task completed successfully");
            }

            if (task.IsFaulted)
            {
                if (task.Exception != null)
                {
                    var exceptions = task.Exception.Flatten().InnerExceptions;
                    foreach (var exception in exceptions)
                    {
                        Console.WriteLine(exception.Message);
                    }
                }
                Console.WriteLine("The task failed");
            }
        }

        static async Task DoWorkAsync(CancellationToken cancellationToken)
        {
            await Task.Run(() => DoWork(cancellationToken), cancellationToken);
        }

        static void DoWork(CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();

            Console.WriteLine("DoWork() is started");

            // Uncomment the following line of code to put the task in a 'faulted' state
            //throw new Exception();

            for (var count = 0; count < 10; count++)
            {
                if (cancellationToken.IsCancellationRequested)
                {
                    Console.WriteLine("Get a cancelation request");
                    cancellationToken.ThrowIfCancellationRequested();
                }
                else
                {
                    Thread.Sleep(500);
                    Console.WriteLine("Count : " + count);
                }
            }
            Console.WriteLine("DoWork() is finished");
        }
    }
}

当我让应用程序完成时,我正确收到“任务已成功完成”消息。

现在,当我按下 CTRL+C 时,触发取消已启动任务(请参阅通过 myHandler 拦截),我正确地收到“任务已取消”消息。但我也收到“任务成功完成”消息。我没想到任务也会显示为完成,因为我取消了它。 如果我取消注释 DoWork() 方法中的 throw new Exception(); 行,我会正确收到“任务失败”消息,以及“任务成功完成”消息。 我的假设错了吗?这是设计的吗?还是我完全错过了其他东西?

我当然可以通过添加如下额外检查来解决这个问题:

if (task.IsCompleted && !task.IsCanceled)
{
    Console.WriteLine("The task completed successfully");
}

但我不确定这是否是正确的方法,或者我的程序中是否有其他东西导致了这个完成状态。

提前感谢您对此事的意见和/或澄清。

【问题讨论】:

    标签: c# task-parallel-library cancellation


    【解决方案1】:

    Task.IsCompleted 的文档说

    当任务处于三种最终状态之一时,IsCompleted 将返回 true:RanToCompletion、Faulted 或 Canceled。

    所以IsCompleted 至少告诉你任务不再运行了。它不指示任务是成功完成、失败还是被取消。

    【讨论】:

    • 谢谢!我真的应该开始阅读更多文档,而不是自己做假设。
    • 这是正确的。您希望检查 TaskStatus 属性以验证取消和完成,因为被取消的任务是有效的完成条件。
    • @KevinD 是或开始就 SO 提出更多问题。但是这个问题可以通过阅读文档轻松解决。
    • @KevinD:我有Status 的视觉描述和相关属性(例如,IsCompletedon my blog
    【解决方案2】:

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-31
      • 1970-01-01
      • 1970-01-01
      • 2014-07-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多