在下面的代码中,我预计结果为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
我想我错过了一些非常明显的东西,我需要在第一段代码中修复它才能让它返回3
更新 我已经看过这个Solution这就是为什么我没有使用Task.Run但它并没有真正有所作为
答案 0 :(得分:3)
由值类型与参考类型语义的差异引起的案例之间的差异。 int
是值类型,因此在返回时复制,并且不会看到对sum
变量的任何后续更改。数组是引用类型,因此只返回复制引用,因此子任务所做的数组中的任何更改都是可见的,因为它是相同的数组。要使您的第一个案例有效,您需要使用某种引用类型替换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();
}