TaskCreationOptions.AttachedToParent不等待子任务

时间:2013-01-04 02:55:02

标签: c# async-await

根据MSDN:

  

您可以使用AttachedToParent选项表达结构化任务   并行性,因为父任务隐含地等待所有孩子   完成的任务。

所以我有这段代码:

public async Task<int> GetIntAsync()
{
    var childTask = Task.Factory.StartNew(async () =>
    {
        await Task.Delay(1000);
    },TaskCreationOptions.AttachedToParent);

    return 1;
}

public async Task<ActionResult> Index()
{
    var watch = Stopwatch.StartNew();
    var task = GetIntAsync();
    var result = await task;
    var time = watch.ElapsedMilliseconds;

    return View();  
}

我想知道为什么时间是0而不是1000。

3 个答案:

答案 0 :(得分:5)

使用基于任务的异步模式(TAP)的代码通常不使用AttachedToParentAttachedToParent是任务并行库(TPL)设计的一部分。 TPL和TAP都共享相同的Task类型,但在TAP代码中应该避免许多TPL成员。

在TAP中,您可以通过“父”异步方法await从“子”异步方法返回的任务来支持“父”和“子”异步方法的概念:

public async Task<int> GetIntAsync()
{
  var childTask = Task.Run(() =>
  {
    ...
    await Task.Delay(1000);
    ...
  });
  ...

  await childTask;
  return 1;
}

答案 1 :(得分:4)

AttachedToParent仅附加到计划的任务。您的异步方法返回的任务未安排,而是(隐式)来自TaskCompletionSource

答案 2 :(得分:1)

这是一个适用于动态数量的子任务的解决方案。

一般来说,使用列表是天真的。

public async Task<int> GetIntAsync()
{
    var childTasks = new List<Task>();

    while (...)
    {
        ...
        childTasks.Add(Task.Run(...));
        ...
    }

    await Task.WhenAll(childTasks);

    return 1;
}

例如,如果子任务是短暂的,并且快速且无限制地创建新的任务,则列表将溢出。

相反,我们只能使用一项任务。

public async Task<int> GetIntAsync()
{
    var childrenTask = Task.WhenAll();

    while (...)
    {
        ...
        childrenTask = Task.WhenAll(Task.Run(...), childrenTask);
        ...
    }

    await childrenTask;

    return 1;
}

请注意,这是一个任务的链接列表,一旦任务完成就会收缩。