考慮下面的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說:怪異編譯器行爲等待關鍵字
返回值是:任務(TResult)表示由函數返回的任務(TResult)的代理。
它還說,在備註:
的
Run<TResult>(Func<Task<TResult>>)
方法是通過語言使用 編譯器支持異步和等待關鍵字。它並不打算從用戶代碼直接調用 。
所以,它看起來像我不應該在我的代碼中使用此重載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,其中L1具有它們都不和L2具有兩者
令人驚訝地,L3現在被認爲是作爲Task<Task<Task<Task<Dummy>>>>
,不同於L1和L2 ,其中兩個被認爲Task<Dummy>
我的問題:
1.
是什麼原因導致的編譯器從L1和L2區別對待L3。爲什麼簡單地增加'async'
到L1(或L2移除await
)使編譯器以不同的方式對待它?
2.
如果您將更多Task.Run級聯到L1/L2/L3,Visual Studio將崩潰。我使用VS2013,如果我級聯了5層或更多層的Task.Run,它會崩潰。 4層是最好的我可以得到,這就是爲什麼我用4層作爲我的例子。只有我嗎 ? 編譯器在翻譯Task.Run時會發生什麼情況?
由於
我得到了7個關卡,然後VS2013變得沒有反應。這可能是我的擴展之一(特別是Resharper),這是應該指責的;我沒有去檢查那個。 – 2015-02-06 02:27:08