取消的任务也显示为已完成
Canceled task also appears as completed
我正在研究异步等待和取消,以便对此事有更多了解。为此,我制作了以下控制台应用程序:
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");
}
}
}
当我让应用程序完成时,我正确地收到了 "The task completed successfully" 消息。
现在,当我按下 CTRL+C 时,这会触发对已启动任务的取消(请参阅 myHandler
中的拦截),我会正确地收到 "The task was canceled" 消息。但我也收到 "The task completed successfully" 消息。我没想到任务也会显示为已完成,因为我取消了它。
如果我取消注释 DoWork()
方法中的 throw new Exception();
行,我会正确地收到 "The task failed" 消息,还有 "The task completed successfully" 消息。
我的假设错了吗?这是设计好的吗?还是我完全错过了其他东西?
我当然可以通过添加如下额外检查来解决这个问题:
if (task.IsCompleted && !task.IsCanceled)
{
Console.WriteLine("The task completed successfully");
}
但我不确定这是不是正确的方法,或者我的程序中是否有其他原因导致了此完成状态。
提前感谢您对此事的输入and/or澄清。
Task.IsCompleted 的文档说
IsCompleted will return true when the task is in one of the three final states: RanToCompletion, Faulted, or Canceled.
所以 IsCompleted
至少告诉您任务不再是 运行。它不表示任务是成功完成、失败还是被取消。
我正在研究异步等待和取消,以便对此事有更多了解。为此,我制作了以下控制台应用程序:
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");
}
}
}
当我让应用程序完成时,我正确地收到了 "The task completed successfully" 消息。
现在,当我按下 CTRL+C 时,这会触发对已启动任务的取消(请参阅 myHandler
中的拦截),我会正确地收到 "The task was canceled" 消息。但我也收到 "The task completed successfully" 消息。我没想到任务也会显示为已完成,因为我取消了它。
如果我取消注释 DoWork()
方法中的 throw new Exception();
行,我会正确地收到 "The task failed" 消息,还有 "The task completed successfully" 消息。
我的假设错了吗?这是设计好的吗?还是我完全错过了其他东西?
我当然可以通过添加如下额外检查来解决这个问题:
if (task.IsCompleted && !task.IsCanceled)
{
Console.WriteLine("The task completed successfully");
}
但我不确定这是不是正确的方法,或者我的程序中是否有其他原因导致了此完成状态。
提前感谢您对此事的输入and/or澄清。
Task.IsCompleted 的文档说
IsCompleted will return true when the task is in one of the three final states: RanToCompletion, Faulted, or Canceled.
所以 IsCompleted
至少告诉您任务不再是 运行。它不表示任务是成功完成、失败还是被取消。