我在理解AttachedToParent
参数如何工作时遇到问题。
这是示例代码:
public static void Main(string[] args)
{
Task<int[]> parentTask = Task.Run(()=>
{
int[] results = new int[3];
Task t1 = new Task(() => { Thread.Sleep(3000); results[0] = 0; }, TaskCreationOptions.AttachedToParent);
Task t2 = new Task(() => { Thread.Sleep(3000); results[1] = 1; }, TaskCreationOptions.AttachedToParent);
Task t3 = new Task(() => { Thread.Sleep(3000); results[2] = 2; }, TaskCreationOptions.AttachedToParent);
t1.Start();
t2.Start();
t3.Start();
return results;
});
Task finalTask = parentTask.ContinueWith(parent =>
{
foreach (int result in parent.Result)
{
Console.WriteLine(result);
}
});
finalTask.Wait();
Console.ReadLine();
}
据我了解,当一个任务有子任务时,所有子任务都准备好后,父任务就完成了。这个例子的问题是输出看起来像这样:
0
0
0
这意味着父任务没有等待其子任务完成。获得有效结果的唯一方法0 1 2
是在所有子Taks上使用Wait,方法是在return results;
语句之前添加如下代码:
Task[] taskList = { t1, t2, t3 };
Task.WaitAll(taskList);
我的问题是这个。TaskCreationOptions.AttachedToParent
当我们还必须为每个子Task手动调用Wait方法时,为什么使用?
编辑:
当我编写此问题时,我对代码进行了一些更改,现在AttachedToParent运行良好。唯一的区别是,我使用了parentTask.Start();
而不是Task.Run();
。
public static void Main(string[] args)
{
Task<int[]> parentTask = new Task<int[]>(()=>
{
int[] results = new int[3];
Task t1 = new Task(() => { Thread.Sleep(3000); results[0] = 0; }, TaskCreationOptions.AttachedToParent);
Task t2 = new Task(() => { Thread.Sleep(3000); results[1] = 1; }, TaskCreationOptions.AttachedToParent);
Task t3 = new Task(() => { Thread.Sleep(3000); results[2] = 2; }, TaskCreationOptions.AttachedToParent);
t1.Start();
t2.Start();
t3.Start();
//Task[] taskList = { t1, t2, t3 };
//Task.WaitAll(taskList);
return results;
});
parentTask.Start();
Task finalTask = parentTask.ContinueWith(parent =>
{
foreach (int result in parent.Result)
{
Console.WriteLine(result);
}
});
finalTask.Wait();
Console.ReadLine();
}
我仍然不明白为什么第一个示例有问题。
查看此博客文章:Task.Run与Task.Factory.StartNew
第一个例子:
Task.Run(someAction);
是简化的等效方法:
Task.Factory.StartNew(someAction,
CancellationToken.None,
TaskCreationOptions.DenyChildAttach,
TaskScheduler.Default);
我很少做研究,使用反射器,这是方法的来源 Task.Run
public static Task Run(Func<Task> function, CancellationToken cancellationToken)
{
if (function == null)
throw new ArgumentNullException("function");
cancellationToken.ThrowIfSourceDisposed();
if (cancellationToken.IsCancellationRequested)
return Task.FromCancellation(cancellationToken);
else
return (Task) new UnwrapPromise<VoidTaskResult>(
(Task) Task<Task>.Factory.StartNew(function,
cancellationToken,
TaskCreationOptions.DenyChildAttach,
TaskScheduler.Default),
true);
}
方法的重要参数Task.Factory.StartNew
是TaskCreationOptions creationOptions
。在方法中Task.Factory.StartNew
,参数等于TaskCreationOptions.DenyChildAttach
。这意味着
如果尝试将子任务附加到创建的任务,则将抛出InvalidOperationException
您需要进行更改以TaskCreationOptions.None
实现正确的代码行为。
方法Task.Run
不提供更改TaskCreationOptions参数的功能。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句