6

根据 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。

4

3 回答 3

7

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

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

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

  await childTask;
  return 1;
}
于 2013-01-04T19:06:16.103 回答
4

AttachedToParent 仅附加到计划的任务。您的 async 方法返回的 Task 不是计划的,而是(隐式)来自 TaskCompletionSource

于 2013-01-04T03:03:07.450 回答
2

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

一般来说,使用列表是幼稚的。

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;
}

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

于 2015-02-01T23:32:39.147 回答