当我们链接ContinueWith调用时是否创建了新的Task对象?

时间:2018-02-19 21:14:49

标签: c# async-await task compiler-optimization value-type

考虑一种情况,当方法返回一个任务链时,就像这个(我主要使用.net 3.5,所以示例使用ContinueWith,但await的问题是相同的):

 static Task UnwrappedTask()
    {
        Task<Task> t = TestStr().ContinueWith( (
            return  GetTaskFromString(s).ContinueWith(
                // returns a task 
            });
        });
        return t.Unwrap();
    }

    static async Task GetTaskFromString(string str)
    {
        await Task.Delay(3000);
    }

    static async Task<string> TestStr()
    {
        await Task.Delay(3000);
        return "res";
    }

每次从ContinueWith()返回时是否都创建了一个新的Task对象,或者编译器是否以某种方式重用了该实例?我对Value类型Task.Result在这种情况下的行为感兴趣:它是在那些时候复制的,还是包装器Task类提供了一种将它传输到最外层方法的有效方法?

1 个答案:

答案 0 :(得分:3)

ContinueWith始终创建新任务。它不可能做任何其他事情。该方法的整个设计是ContinueWith采用现有的Task,在完成后执行一些任意方法,并产生新的结果。 ContinueWith的结果永远不会与它作为延续的任务完全相同,因此它不能仅仅重复使用它。根据设计,它不是变异它正在添加延续的任务(至少以任何外部可见的方式,技术上存储延续到火是任务的内部变异)。