为什么任务未显示已取消状态

Mri*_*boj 2 c# task task-parallel-library async-await

我测试的Linqpad创建了一个简单的控制台应用程序,思路是有工作的保证理解Task并创建工作,当逻辑Task完成,故障或取消.我想只在Task完成但没有出错或取消时才执行逻辑.

void Main()
{
    CancellationTokenSource cts = new CancellationTokenSource(new TimeSpan(0,0,0,0,1000));

    Task t = Task.Run(() => Work(),cts.Token);
    try
    {
        t.Wait();
    }
    catch
    {
    }

    ("Completed :: " + t.IsCompleted).Dump();
    ("Canceled :: " + t.IsCanceled).Dump();
    ("Faulted :: " + t.IsFaulted).Dump();
}

public async Task Work()
{
    await Task.Delay(3000);
}
Run Code Online (Sandbox Code Playgroud)

以下是问题:

  1. 我能够自信地弄清楚已完成状态和故障状态,但即使在我看来这个代码应该导致任务取消,IsCanceled属性的值总是假的.

  2. 理想情况下,当Task出现故障时,即使我在try catch块中静默捕获异常,它也应显示IsCompleted为false,但它始终保持为true,目前Linqpad没有继续出错选项,但我假设,它如果我可以继续错误,将会变为假

Sef*_*efe 5

我能够自信地找出Completed和Faulted状态,但即使在我看来这个代码应该导致Task取消,IsCanceled属性的值总是假的.

取消时没有自动化.要传递CancellationTokenTask.Run.如果在任务启动时取消,则取消将中断启动过程.任务运行后,任务的方法是检查取消令牌的责任.Wait不这样做.它甚至不知道取消令牌.因此,任务永远不会变成被取消的状态.

这是您观察取消的方式:

void Main()
{
    CancellationTokenSource cts = new CancellationTokenSource(new TimeSpan(0,0,0,0,1000));

    Task t = Task.Run(() => Work(cts.Token),cts.Token);
    try
    {
        t.Wait();
    }
    catch
    {
    }

    ("Completed :: " + t.IsCompleted).Dump();
    ("Canceled :: " + t.IsCanceled).Dump();
    ("Faulted :: " + t.IsFaulted).Dump();
}

public async Task Work(CancellationToken token)
{
    await Task.Delay(3000, token);
}
Run Code Online (Sandbox Code Playgroud)

理想情况下,当Task出现故障时,即使我在try catch块中静默捕获异常,它也应该将IsCompleted显示为false,但它始终保持为true

检查MSDN:

当任务处于以下三种最终状态之一时,IsCompleted将返回true:RanToCompletion,Faulted或Cancelled.


Ste*_*ary 5

其他人已经注意到你的代码没有观察到CancellationToken,这就是为什么任务没有被取消.

我会回答这部分问题:

我想只在Task完成但没有出现故障或取消时才执行逻辑.

要做到这一点,请await在完成任务后输入逻辑:

await t;
// Your logic here.
Run Code Online (Sandbox Code Playgroud)

使用IsCanceled/ IsFaulted/ IsCompleted控制流是代码气味.