C#中Task介紹

在C#中,Task類是異步編程的重要工具之一,它提供了一系列用於創建、啓動和管理異步任務的常用方法,主要包括以下幾個:

  1. Task.Run:創建並開始執行一個異步任務。 
Task task = Task.Run(() =>
{
    // 執行一些耗時操作
});
  1. Task.Factory.StartNew:使用TaskFactory類來創建並啓動一個異步任務,並可以配置任務的類型和選項等。
Task task = Task.Factory.StartNew(() =>
{
    // 執行一些耗時操作
}, TaskCreationOptions.LongRunning);
  1. Task.FromResult:將一個已完成的任務包裝成一個新的Task對象返回。 
Task<int> completedTask = Task.FromResult(42);
  1. Task.Delay:創建並返回一個暫停指定時間後完成的異步任務。 
await Task.Delay(TimeSpan.FromSeconds(5));
  1. Task.WaitAny:等待任意一個異步任務完成後繼續執行。它可以阻塞執行當前代碼的線程,不建議在UI線程中使用。
Task<int>[] tasks = new Task<int>[3];
tasks[0] = Task.Run(() => DoWork());
tasks[1] = Task.Run(() => DoMoreWork());
tasks[2] = Task.Run(() => DoOtherWork());

int index = await Task.WaitAny(tasks);
int result = tasks[index].Result;
  1. Task.WaitAll:等待所有異步任務完成後繼續執行。它同樣可以阻塞線程運行,不建議在UI線程中使用。
Task<int>[] tasks = new Task<int>[3];
tasks[0] = Task.Run(() => DoWork());
tasks[1] = Task.Run(() => DoMoreWork());
tasks[2] = Task.Run(() => DoOtherWork());

await Task.WaitAll(tasks);
int result1 = await tasks[0];
int result2 = await tasks[1];
int result3 = await tasks[2];
  1. Task.ContinueWith:使用新的任務來代表原有任務的完成情況,支持鏈式調用。在原有任務完成後,可以根據需要添加一些後續操作。 
Task<int> task1 = Task.Run(() => DoWork());
Task<string> task2 = task1.ContinueWith(t => FormatResult(t.Result));

需要注意的是,在使用Task時,應該避免出現async void方法、潛在死鎖、延遲造成的線程啓動等問題,以及適時地將一些阻塞操作轉換爲異步操作,從而獲得更高效的異步編程體驗。

Task.Run和Task.Factory.StartNew

C#中的Task.Run和Task.Factory.StartNew方法都可以用於創建並啓動一個異步任務,它們本質上都是將一個委託或Lambda表達式作爲方法參數來實現異步執行。然而,它們之間確實存在一些差異,包括以下幾個方面:

  1. Task.Factory.StartNew方法允許使用TaskCreationOptions枚舉類型的選項來配置任務的行爲和特性,比如指定是否應該爲長時間運行的任務分配單獨的線程,或者是否應該禁用任務延遲等。而Task.Run方法則沒有提供這樣的選項,會使用默認設置。

  2. Task.Factory.StartNew方法返回一個Task,而Task.Run方法直接返回一個已啓動的Task。由於這種區別,使用Task.Run方法時更加簡便和直接,不需要再使用StartNew方法的Task.Run(delegate)格式寫代碼。

  3. 目前,推薦使用Task.Run方法而不是Task.Factory.StartNew方法。這是由於在.NET Framework 4.5中對Task.Run進行了優化,使其更容易使用、更可讀、更安全、更高效,並避免了一些常見但難以處理的問題,比如任務調度延遲和死鎖等。

綜上所述,Task.Run方法比Task.Factory.StartNew方法更常用和更受推薦,既可讀性更好,又能夠實現大多數異步操作需求。但是,在某些特定場合下,使用Task.Factory.StartNew能夠提供更精細的線程投放控制能力和一些必要特性。

需要注意的是,在使用Task.Run或Task.Factory.StartNew時,開啓的線程數不應該過多,要適當評估運行環境的CPU和I/O資源,並選擇正確的選項進行任務調度,避免出現不必要的資源浪費、線程飢餓和隊列擁堵等

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章