c# - 子任务取消,父任务完成?

标签 c# task-parallel-library

我试图了解 .net 任务在附加子项时的行为。

我有以下测试代码:

void Test()
{
    var tokenSource = new CancellationTokenSource();
    var token = tokenSource.Token;

    Task child = null;
    var parent = Task.Factory.StartNew(() =>
    {
        child = Task.Factory.StartNew(() =>
        {
            while (!token.IsCancellationRequested)
                Thread.Sleep(100);
            token.ThrowIfCancellationRequested();
        }, token, TaskCreationOptions.AttachedToParent, TaskScheduler.Default);
    }, token);

    Thread.Sleep(500);

    Debug.WriteLine("State of parent before cancel is {0}", parent.Status);
    Debug.WriteLine("State of child before cancel is {0}", child.Status);

    tokenSource.Cancel();
    Thread.Sleep(500);

    Debug.WriteLine("State of parent is {0}", parent.Status);
    Debug.WriteLine("State of child is {0}", child.Status);
}

结果是:

State of parent before cancel is WaitingForChildrenToComplete
State of child before cancel is Running
A first chance exception of type 'System.OperationCanceledException' occurred in mscorlib.dll
State of parent is RanToCompletion
State of child is Canceled

显然父任务状态不是Canceled,即使 两个任务共享 token ,并附加子项。

如何让父任务在发生取消时返回状态 Canceled

注意 如果我抛出异常,两个任务都会返回 Faulted

最佳答案

这是 MSDN 上规定的预期行为。父任务必须 wait (向下滚动到取消部分)子任务。父任务必须处理所有良性故障(如取消)。

要使您的父任务失败,只需等待并传递 token :

Task child = null;
var parent = Task.Factory.StartNew(() =>
{
  child = Task.Factory.StartNew(() =>
  {
    while (!token.IsCancellationRequested) Thread.Sleep(100);
    token.ThrowIfCancellationRequested();
  }, token, TaskCreationOptions.AttachedToParent, TaskScheduler.Default);

  // This is the magic line.
  child.Wait(token);
}, token);

如果您使用这段代码来做一些有成效的事情,而不仅仅是为了测试,您还应该考虑使用支持 async 委托(delegate)的简化的 Task.Run() Task.Factory.StartNew()。这article很有趣。

关于c# - 子任务取消,父任务完成?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28564074/

相关文章:

c# - 使用 HttpRequestMessageProperty 和 OperationContextScope 的 WCF HTTP header

c# - 使用 Json.NET 序列化时忽略特定数据类型?

c# - 为什么我的任务没有显示在 Visual Studio 任务窗口中?

c# - Task.Factory.StartNew() 是否保证使用调用线程之外的另一个线程?

.net - 终止 .NET 4 TPL 中的死锁任务

c# - 是否可以在核心之间划分工作?

c# - 通过 HtmlAgilityPack 获取属性的值

c# - GoToWebinar - 请求不是预期格式 - RestSharp

c# - 为什么我会收到 StringFormat 错误?

c# - 为什么这个对象为空?