Task.Run vs Task.Factory.StartNew


Task.Run 和 Task.Factory.StartNew 都可以把一段要執行的代碼放到ThreadPool thread中去執行。Task.Factory.StartNew是.Net 4.0中引入的,而Task.Run則是在.Net 4.5中引入,首要目的是為了簡化Task.Factory.StartNew的使用。簡言之,

Task.Run(someAction)

Task.Factory.StartNew(someAction, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);

是基本等價的。

說基本等價,是因為這兩種用法還是有不完全相同的地方。

比如下面的代碼

var t = Task.Factory.StartNew(delegate
 {
        return 42;
 }); 

通過Task.Factory.StartNew ,我們把一個TResult是int的delegate變成了Task<int>類型。

 

那么下面的代碼呢

var t = Task.Factory.StartNew(async delegate
{
     await Task.Delay(1000);
     return 42;
});

傳給Task.Factory.StartNew的是一個asyn的delegate,即是Task<int>類型。通過Task.Factory.StartNew,得到的t是一個Task<Task<int>>類型。

這時候,如果我們await t,實際上,當它返回時,並不是這個async的delegate執行完成了,而是得到了Task<int>。這通常不是我們想要的結果。

 

為了處理這種情況,.Net 4引入了Unwrap函數。Unwrap有兩個重載方法,一個是作用於類型Task<Task>上,另外一個是作用於Task<Task<TResult>>上。

在Task<Task>上調用Unwrap會返回一個新的Task,它代表這內部Task最終是否完成。

 

回到前面的例子,如果我想讓t代表內部的async delegate,那么可以這樣

var t = Task.Factory.StartNew(async delegate
{
       await Task.Delay(1000);
       return 42;
}).Unwrap();

 

接下來講Task.Run。由於上面所述的用法是一種很常見的需求,因此在.Net 4.5中,

var t = Task.Run(async delegate
{
       await Task.Delay(1000);
       return 42;
});

上述代碼就直接得到的是Task<int>,而不是Task<Task<int>>。

即該代碼等價於

var t = Task.Factory.StartNew(async delegate 
{ 
    await Task.Delay(1000);  
    return 42; 
}, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default).Unwrap();

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM