简体   繁体   English

取消父任务后,NotOnRanToCompletion继续运行不运行

[英]NotOnRanToCompletion Continuation doesn't run when parent task is cancelled

I'm trying to test a scenario where I have a task that can be cancelled, and a continuation that should be running if the antecedent task doesn't complete. 我正在尝试测试一个场景,该场景中有一个可以取消的任务,并且如果前一个任务没有完成,则应该继续运行该任务。 A sample of the code is like this: 代码示例如下:

static void Main(string[] args)
{
    var source = new CancellationTokenSource();
    var task = Task.Factory.StartNew(() =>
        {
            while (true)
            {
                source.Token.ThrowIfCancellationRequested();
            }
        }, source.Token);

    var continuation = task.ContinueWith(t =>
        {
            Console.WriteLine("Continuation");
            if (t.Status == TaskStatus.Faulted)
            {
                Console.WriteLine("Antecedent Faulted: " + t.Exception.Message);
            }
        }, source.Token, TaskContinuationOptions.NotOnRanToCompletion | TaskContinuationOptions.AttachedToParent, TaskScheduler.Current);

    var cancellation = Task.Factory.StartNew(() =>
        {
            Thread.Sleep(1000);
            source.Cancel();
        });

    try
    {
        continuation.Wait();
    }
    catch (AggregateException)
    {
        Console.WriteLine("AggregateException");
    }

    Console.WriteLine("Done");
    while (!Console.KeyAvailable) { }
}

The output of this program is: 该程序的输出为:

AggregateException
Done

To a certain extent, I get it. 在一定程度上,我明白了。 The primary task was cancelled, which ends up throwing a TaskCanceledException which gets wrapped in the AggregateException. 主要任务已取消,最终引发了TaskCanceledException,该任务被包装在AggregateException中。 The question is, is this expected behaviour? 问题是,这是预期的行为吗? If so, what use is TaskStatus.Faulted in a continuation, if that continuation isn't getting executed? 如果是这样,如果未执行该延续,则TaskStatus.Faulted在延续中有什么用? I even set a looping check for ConsoleKeyAvailable just in case the continuation does get run as well as the AggregateException getting thrown. 我什至为ConsoleKeyAvailable设置了一个循环检查,以防继续运行以及抛出AggregateException的情况发生。

I believe the reason this is occurring is you are passing source.Token as the CancellationToken for the call to task.ContinueWith . 我相信这是发生的原因是要传递source.Token作为CancellationToken呼叫到task.ContinueWith Despite passing NotOnRanToCompletion as the continuation options, the fact that the token is cancelled before the continuation task ever starts means the scheduler can immediately transition it to the canceled state without actually running it. 尽管将NotOnRanToCompletion作为继续选项传递,但令牌在继续任务启动之前被取消的事实意味着调度程序可以立即将其转换为取消状态,而无需实际运行它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM