[.NET]Thread與Task的區別


前言

在學習Thread和Task之前,首先要理解以下概念:

  • 進程與線程
  • 同步與異步
  • 阻塞與非阻塞

1、進程(process)

當一個程序開始運行時,它就是一個進程,進程包括運行中的程序和程序所使用到的內存和系統資源。

而一個進程又是由多個線程所組成的。

2、線程(thread)

線程是程序中的一個執行流,每個線程都有自己的專有寄存器(棧指針、程序計數器等),但代碼區是共享的。

多線程是指程序中包含多個執行流,即在一個程序中可以同時運行多個不同的線程來執行不同的任務,也就是說允許單個程序創建多個並行執行的線程來完成各自的任務。

3、同步(sync)

發出一個功能調用時,在沒有得到結果之前,該調用就不返回。

4、異步(async)

與同步相對,調用在發出之后,這個調用就直接返回了,所以沒有返回結果。當這個調用完成后,一般通過狀態、通知和回調來通知調用者。對於異步調用,調用的返回並不受調用者控制。

通知調用者的三種方式:

  • 狀態:即監聽被調用者的狀態(輪詢),調用者需要每隔一定時間檢查一次,效率會很低。
  • 通知:當被調用者執行完成后,發出通知告知調用者,無需消耗太多性能。
  • 回調:與通知類似,當被調用者執行完成后,會調用調用者提供的回調函數。

5、阻塞(block)

阻塞調用是指調用結果返回(或者收到通知)之前,當前線程會被掛起,即不繼續執行后續操作。

簡單來說,等前一件做完了才能做下一件事。

6、非阻塞(non-block)

非阻塞調用指在不能立刻得到結果之前,該調用不會阻塞當前線程。

什么是 Thread

.NET Framework 在 System.Threading 下提供線程的相關類。一個線程是一組執行指令。

Thread

什么是 Task

.NET Framework 提供了 Threading.Task 類,允許創建任務和異步運行它們。Task 有Wait、ContinueWith、Cancel等操作,有返回值。

Task

Thread與Task的區別

Thread 類主要用於實現線程的創建以及執行。

Task 類表示以異步方式執行的單個操作。

1、Task 是基於 Thread 的,是比較高層級的封裝,Task 最終還是需要 Thread 來執行

2、Task 默認使用后台線程執行,Thread 默認使用前台線程

static void Main(string[] args)
{
    Thread thread = new Thread(obj => { Thread.Sleep(3000); });
    thread.Start();
}

上面代碼,主程序在3秒后結束。

static void Main(string[] args)
{
    Task<int> task = new Task<int>(() => 
    {
        Thread,Sleep(3000);
        return 1;
    });
    task.Start();
}

而這段代碼,會瞬間結束。

3、Task 可以有返回值,Thread 沒有返回值

雖然 Thread 可以通過 Start 方法參數來進行返回值處理,但十分不便。

public void Start (object parameter);
static void Main(string[] args)
{  
    Task task = new Task(LongRunningTask);
    task.Start();
    Console.WriteLine(task.Result);
}
private static int LongRunningTask()
{
    Thread.Sleep(3000);
    return 1;
}

4、Task 可以執行后續操作,Thread 不能執行后續操作

static void Main(string[] args)
{
    Task task = new Task(LongRunningTask);
    task.Start();
    Task childTask = task.ContinueWith(SquareOfNumber);
    Console.WriteLine("Sqaure of number is :"+ childTask.Result);
    Console.WriteLine("The number is :" + task.Result);
}
private static int LongRunningTask()
{
    Thread.Sleep(3000);
    return 2;
}
private static int SquareOfNumber(Task obj)
{
    return obj.Result * obj.Result;
}

5、Task 可取消任務執行,Thread 不行

static void Main(string[] args)
{
    using (var cts = new CancellationTokenSource())
    {
        Task task = new Task(() => { LongRunningTask(cts.Token); });
        task.Start();
        Console.WriteLine("Operation Performing...");
        if(Console.ReadKey().Key == ConsoleKey.C)
        {
            Console.WriteLine("Cancelling..");
            cts.Cancel();
        }                
        Console.Read();
    }
}
private static void LongRunningTask(CancellationToken token)
{
    for (int i = 0; i < 10000000; i++)
    {
        if(token.IsCancellationRequested)
        {
            break;
        }
        else
        {                  
            Console.WriteLine(i);
        }               
    }          
}

6、異常傳播

Thread 在父方法上獲取不到異常,而 Task 可以。

參考文檔


免責聲明!

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



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