所以这是我的代码
Task<int[]> parent = Task.Run(() =>
{
var result = new int[3];
TaskFactory tf = new TaskFactory(TaskCreationOptions.AttachedToParent, TaskContinuationOptions.ExecuteSynchronously);
for (int i = 0; i < result.Length; i++)
{
int j = i;
tf.StartNew(() => result[j] = GetRandomNumber(j));
}
return result;
});
var finalTask = parent.ContinueWith(parentTask =>
{
foreach (var i in parentTask.Result)
{
Console.WriteLine(i);
}
});
finalTask.Wait();
基本上我创建了3个Task
,它们是Task
的孩子,叫做父母(我猜)。我要求父任务等待所有三个子任务完成。之后,由于finalTask
这个状态,finalTask.Wait();
将等待执行。但事情并没有像预期的那样发生。我的意思是应用程序在任何GetRandomNumber
调用完成之前退出。这里的代码的某些部分是从书中复制的,该书表明那些父任务应该等待子任务完成,这显然没有发生。我在这里错过了什么吗?
这就是GetRandomNumber的作用
public static int GetRandomNumber(int ii)
{
Random rand = new Random();
for (int i = 0; i < 1000000000; i++) { } // imitate some jobs
return rand.Next(1000);
}
此代码执行相同的操作
Task<int[]> parent = Task.Run(() =>
{
var result = new int[3];
for (int i = 0; i < result.Length; i++)
{
int j = i;
new Task(() => result[j] = GetRandomNumber(j), TaskCreationOptions.AttachedToParent).Start();
}
return result;
});
答案 0 :(得分:13)
此行为是由于您使用Task.Run
方法,该方法禁止将子任务附加到父级:
Run
方法是StartNew
方法的简单替代方法。它创建了一个任务[其]CreationOptions
属性值为TaskCreationOptions.DenyChildAttach
。
要解决此问题,只需更改
中的第一行即可Task<int[]> parent = Task.Run(() =>
到
Task<int[]> parent = Task.Factory.StartNew(() =>
答案 1 :(得分:8)
在Task.Run的文档中,您会发现它指定了
其CreationOptions属性值为TaskCreationOptions.DenyChildAttach。
因此,即使您指定TaskCreationOptions.AttachedToParent
,也会被忽略。
答案 2 :(得分:2)
请使用以下代码:
static void RunParentTask()
{
Task<int[]> parent = Task.Factory.StartNew<int[]>(() =>
{
var results = new int[3];
TaskFactory<int> factory = new TaskFactory<int>(TaskCreationOptions.AttachedToParent,
TaskContinuationOptions.ExecuteSynchronously);
factory.StartNew(() => results[0] = 1);
factory.StartNew(() => results[1] = 2);
factory.StartNew(() => results[2] = 3);
return results;
});
parent.Wait();
foreach (var item in parent.Result)
{
Console.WriteLine(item);
}
}