繁体   English   中英

父任务忽略子任务

[英]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,我不明白。 奇怪的是,当我将其更改为使用和Array时,它似乎的确做了正确的事情。

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

更新我已经查看了此解决方案 ,这就是为什么我没有使用Task.Run的原因,但并没有真正的改变

值类型与引用类型语义上的差异导致的案例之间的差异。 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();
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM