AttachedToParent的用例是什么?

7
< p > Task.RunTaskFactory.StartNew 的一个区别是默认情况下添加了新的 DenyChildAttach 选项。但是 AttachedToParent 是有原因的。在什么情况下会使用附加的子任务呢?

2个回答

11
AttachedToParent的使用场景是当你有一个嵌套的动态任务并行性场景时。也就是说:
  1. 您需要并行执行算法(即,CPU代码,而不是I/O操作)
  2. 算法必须在运行时执行各种任务(即,算法开始时它不知道需要多少个任务),
  3. 这些任务之间存在分层或父/子关系(即,“父”只有在所有子任务都完成后才应被视为完成,如果任何子任务失败/取消,则父任务也应该失败/取消,即使其代码没有错误)。

由于绝大多数并发问题是基于I/O的(而不是基于CPU的),绝大多数并行性场景是基于数据的并行性(而不是动态任务并行性),并且动态任务并行问题可能具有分层性质,因此几乎从不会出现此情况。

不幸的是,任务(包括异步任务)之间存在逻辑的父/子关系,这导致很多开发人员错误地尝试使用AttachedToParent标志与async任务一起使用。因此,引入了DenyChildAttach标志(防止AttachedToParent生效)。


嗨,史蒂芬!这些年来,AttachedToParent标志的任何实际用例出现了吗? - Rodion Mostovoi
1
@RodionMostovoy:我的回答仍然是最新的。 - Stephen Cleary

1
我能想到的唯一情况已经被async-await所取代。例如,如果你想让一个任务等待其子任务,你可以使用await
var parentTask = Task.Run(async () =>
{
    await Task.Run(() => Thread.Sleep(1000));          
    Console.WriteLine("parent task completed");
});

但在 .Net 4.0 中,你必须对它们进行 Wait() 操作。例如:

var parentTask = Task.Factory.StartNew(() =>
{
    Task.Factory.StartNew(() => Thread.Sleep(1000)).Wait();       
    Console.WriteLine("parent task completed");
});

与第一个示例不同,此示例将阻塞线程直到子任务完成。使用附加任务,我们可以通过以下方式获得相同的行为。
var parentTask = Task.Factory.StartNew(() =>
{
    Task.Factory.StartNew(() => Thread.Sleep(1000), TaskCreationOptions.AttachedToParent)
    .ContinueWith(antecedent => Console.WriteLine("parent task completed", TaskContinuationOptions.AttachedToParent);
});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接