请看以下C#代码
var L1 =
Task.Run(() =>
{
return Task.Run(() =>
{
return Task.Run(() =>
{
return Task.Run(() =>
{
return new Dummy();
});
});
});
});
var L2 =
Task.Run(async () =>
{
return await Task.Run(async () =>
{
return await Task.Run(async () =>
{
return await Task.Run(async () =>
{
return new Dummy();
});
});
});
});
var L3 =
Task.Run(async () =>
{
return Task.Run(async () =>
{
return Task.Run(async () =>
{
return Task.Run(async () =>
{
return new Dummy();
});
});
});
});
var r1 = L1.Result;
var r2 = L2.Result;
var r3 = L3.Result;
======================================================================
乍一看,L1、L2和L3都像是Task<Task<Task<Task<Dummy>>>>
结果,L1和L2只是简单的Task<Dummy>
所以,我查阅了MSDN关于Task.Run的资料
(我的重载Task.Run为:Task.Run<TResult>(Func<Task<TResult>>)
)
MSDN中说:
返回值为:表示函数返回的Task(TResult)的代理的Task(TResult)。
在备注中还指出:
Run<TResult>(Func<Task<TResult>>)
方法由语言编译器用来支持async和await关键字。它不适合直接从用户代码中调用。
看起来,我不应该在我的代码中使用这个重载的Task.Run,
如果我这样做,编译器将剥离多余的Task<Task<Task<...<TResult>>>>
层级,并简单地给出一个Task<TResult>
如果你将鼠标悬停在L1和L2上,它会告诉你它是Task<Dummy>
,而不是我预期的Task<Task<Task<Task<Dummy>>>>
到目前为止还好,直到我看到L3
L3几乎与L1和L2完全相同。区别在于:
L3只有async
关键字,没有await
,而L1和L2则一个没有,一个有
令人惊讶的是,现在L3被视为Task<Task<Task<Task<Dummy>>>>
,而L1和L2都被视为Task<Dummy>
我的问题:
1.
是什么导致编译器将L3与L1和L2区别对待?为什么简单地添加'async'
到L1(或从L2中删除await
)会导致编译器将其区别对待?
2. 如果您将更多的Task.Run级联到L1/L2/L3上,Visual Studio就会崩溃。我正在使用VS2013,如果我级联5个或更多层的Task.Run,它就会崩溃。 4个层是我能得到的最好结果,这就是为什么我以4个层作为我的示例。这只发生在我身上吗?编译器在翻译Task.Run时发生了什么?
谢谢