父任务忽略子任务
Parent Task ignores Child Tasks
在下面的代码中,我预计结果为 3
Task<int> parent = Task.Factory.StartNew(() =>
{
var sum = 0;
TaskFactory tf = new TaskFactory(TaskCreationOptions.AttachedToParent,
TaskContinuationOptions.ExecuteSynchronously);
tf.StartNew(() => sum++);
tf.StartNew(() => sum++);
tf.StartNew(() => sum++);
return sum;
});
var finalTask = parent.ContinueWith(parentTask => Console.WriteLine(parentTask.Result));
finalTask.Wait();
然而结果是0,我不明白。奇怪的是,当我将其更改为使用和数组时,它似乎确实在做正确的事情。
Task<Int32[]> parent = Task.Factory.StartNew(() =>
{
var results = new Int32[3];
TaskFactory tf = new TaskFactory(TaskCreationOptions.AttachedToParent,
TaskContinuationOptions.ExecuteSynchronously);
tf.StartNew(() => results[0] = 0);
tf.StartNew(() => results[1] = 1);
tf.StartNew(() => results[2] = 2);
return results;
});
var finalTask = parent.ContinueWith(
parentTask =>
{
foreach (int i in parentTask.Result)
Console.WriteLine(i);
});
finalTask.Wait();
这里的结果符合预期:
0
1个
2
我想我遗漏了一些非常明显的东西,我需要在第一段代码中修复什么才能拥有它 return 3
更新
我已经看过这个 Solution 这就是为什么我没有使用 Task.Run 但它并没有真正产生影响
值类型与引用类型语义的差异导致案例之间的差异。 int
是值类型,因此它在 return 上进行了复制,并且不会看到对 sum
变量的任何后续更改。数组是引用类型,因此仅在 return 上复制引用,因此子任务对数组所做的任何更改都是可见的,因为它是同一个数组。为了使您的第一个案例有效,您需要将 int
替换为某种引用类型:
public class Reference<T> {
public T Value;
public Reference(T value) {
Value=value;
}
}
public static void Test() {
Task<Reference<int>> parent=Task.Factory.StartNew(() => {
var sum=new Reference<int>(0);
TaskFactory tf=new TaskFactory(TaskCreationOptions.AttachedToParent,
TaskContinuationOptions.ExecuteSynchronously);
tf.StartNew(() => sum.Value++);
tf.StartNew(() => sum.Value++);
tf.StartNew(() => sum.Value++);
return sum;
});
var finalTask=parent.ContinueWith(parentTask => Console.WriteLine(parentTask.Result.Value));
finalTask.Wait();
}
在下面的代码中,我预计结果为 3
Task<int> parent = Task.Factory.StartNew(() =>
{
var sum = 0;
TaskFactory tf = new TaskFactory(TaskCreationOptions.AttachedToParent,
TaskContinuationOptions.ExecuteSynchronously);
tf.StartNew(() => sum++);
tf.StartNew(() => sum++);
tf.StartNew(() => sum++);
return sum;
});
var finalTask = parent.ContinueWith(parentTask => Console.WriteLine(parentTask.Result));
finalTask.Wait();
然而结果是0,我不明白。奇怪的是,当我将其更改为使用和数组时,它似乎确实在做正确的事情。
Task<Int32[]> parent = Task.Factory.StartNew(() =>
{
var results = new Int32[3];
TaskFactory tf = new TaskFactory(TaskCreationOptions.AttachedToParent,
TaskContinuationOptions.ExecuteSynchronously);
tf.StartNew(() => results[0] = 0);
tf.StartNew(() => results[1] = 1);
tf.StartNew(() => results[2] = 2);
return results;
});
var finalTask = parent.ContinueWith(
parentTask =>
{
foreach (int i in parentTask.Result)
Console.WriteLine(i);
});
finalTask.Wait();
这里的结果符合预期: 0 1个 2
我想我遗漏了一些非常明显的东西,我需要在第一段代码中修复什么才能拥有它 return 3
更新 我已经看过这个 Solution 这就是为什么我没有使用 Task.Run 但它并没有真正产生影响
值类型与引用类型语义的差异导致案例之间的差异。 int
是值类型,因此它在 return 上进行了复制,并且不会看到对 sum
变量的任何后续更改。数组是引用类型,因此仅在 return 上复制引用,因此子任务对数组所做的任何更改都是可见的,因为它是同一个数组。为了使您的第一个案例有效,您需要将 int
替换为某种引用类型:
public class Reference<T> {
public T Value;
public Reference(T value) {
Value=value;
}
}
public static void Test() {
Task<Reference<int>> parent=Task.Factory.StartNew(() => {
var sum=new Reference<int>(0);
TaskFactory tf=new TaskFactory(TaskCreationOptions.AttachedToParent,
TaskContinuationOptions.ExecuteSynchronously);
tf.StartNew(() => sum.Value++);
tf.StartNew(() => sum.Value++);
tf.StartNew(() => sum.Value++);
return sum;
});
var finalTask=parent.ContinueWith(parentTask => Console.WriteLine(parentTask.Result.Value));
finalTask.Wait();
}