2012-02-29 90 views
19

從我所瞭解的任務&之間的區別線程是發生在線程池中的任務,而線程是我需要自己管理的東西..(並且該任務可以取消並在任務結束時返回到線程池)任務(System.Threading.Task)和線程之間的差異

但是在一些博客中,我讀到如果操作系統需要創建任務並創建線程=>則創建它將更容易(並摧毀)任務。

有人可以解釋爲什麼創建任務很簡單,線程?

(或者也許我失去了一些東西......)

+17

* job *和a * worker *有什麼區別?工人*做*工作;一名工人不是*工作*。有些工作是由一名工人完成的;一些工作分解成小工作,所有工作都由許多工作人員共同完成。與任務和線程相同;任務不是*一種線程*;一項任務是一份工作,一份工作是一名工作人員。 – 2012-02-29 05:09:52

+3

我聽說過的另一個比喻是,處理器是驅動程序,線程是卡車,任務是負載。駕駛員(處理器)一次只能操作一輛卡車(螺紋),而卡車(螺紋)一次只能牽引一個負載(任務)。您可以根據需要購買任意數量的卡車,但司機在卡車之間切換的時間越多,駕駛時間就越少。貨物可以堆放在等待運輸的倉庫中,倉庫可以優先處理它們,並根據任何規則將其分配給卡車。 – 2012-02-29 16:02:15

回答

20

認爲那是你說的,當你說任務是System.Threading.Task有關。如果是這種情況,那麼你可以這樣想:

  • 程序可以有很多線程,但一個處理器核心一次只能運行一個線程。
    • 線程是非常昂貴的,並且正在運行的線程之間的切換也是非常昂貴的。
    • 所以......有成千上萬個線程在做東西是低效的。想象一下,如果你的老師給 10,000任務要做。你會花很多時間在他們之間騎車,以至於你永遠無法完成任何事情。如果啓動太多線程,CPU也會發生同樣的情況。

要解決這個問題,在.NET框架允許您創建任務。任務是將一些工作捆綁成一個對象,並且它們允許你做有趣的事情,例如捕獲該工作的輸出和連鎖工作(第一個去商店,然後購買雜誌)。

任務安排在一個線程池中。線程的具體數量取決於使用的調度程序,但是默認調度程序會嘗試選擇一定數量的線程,這些線程對於您擁有的CPU內核數量以及實際使用CPU時間花費多少時間來說是最佳的。如果你願意,你甚至可以編寫自己的調度程序來執行某些特定的事情,比如確保該調度程序的所有任務始終在單個線程上運行。

所以將任務視爲待辦事項中的項目。你可能同時做5件事,但如果你的老闆給你10000,他們會堆積在你的收件箱裏,直到你做的前5件事完成。任務與ThreadPool之間的區別在於,任務(正如我前面提到的)可以更好地控制不同工作項目之間的關係(設想多個指令裝訂在一起的待辦事項),而ThreadPool只允許您排隊一堆單獨的單段項目(函數)。

+3

'默認情況下,'ThreadPool'上的任務計劃,但不一定是。如果使用TaskCompletionSource創建它,甚至可能沒有任何直接與「Task」關聯的代碼。 – svick 2012-02-29 14:08:16

11

你聽到任務的兩個不同的概念。第一個是工作的概念,第二個是過程的概念。

很久以前(以計算機術語來說),沒有線程。一個程序的每個運行實例都稱爲一個進程,因爲它只是一個接一個地執行,直到退出。這將過程的直觀理念與工廠裝配線的一系列步驟相匹配。操作系統管理過程抽象。

然後,開發人員開始向工廠添加多條裝配線。現在一個程序可以同時執行多個任務,而且一個庫或者(現在更常見的)操作系統都可以管理每個線程內的步驟的調度。線程是一種輕量級進程,但線程屬於進程,進程中的所有線程共享內存。另一方面,多個過程不能混淆彼此的記憶。因此,Web服務器中的多個線程都可以訪問有關連接的相同信息,但Word無法訪問Excel的內存數據結構,因爲Word和Excel作爲單獨的進程運行。將流程作爲一系列步驟的想法並不真正將流程的模型與線程相匹配,因此有些人將「以前稱爲流程的抽象」稱爲任務。這是您在博客文章中看到的第二個任務定義。請注意,很多人仍然使用「流程」這個詞來表示這件事。

好吧,隨着線程變得更加平庸,開發人員在它們之上添加了更多的抽象,以使它們更易於使用。這導致了線程池的興起,線程池是一個庫管理的「線程池」。你通過圖書館一項工作,圖書館選擇一個線程並在該線程上運行作業。 .NET框架有一個線程池實現,並且在您第一次聽說「任務」時,文檔確實意味着您傳遞給線程池的工作。

因此,從某種意義上說,文檔和博客文章都是正確的。術語任務的超載是混亂的不幸來源。

+1

+1這是一個很好的解釋。我認爲OP在談論'System.Threading.Task'。如果您可以稍微擴大討論範圍以包含TPL的細微差別,那就太好了。 – 2012-02-29 04:25:01

2

任務實際上只是手動旋轉線程的樣板代碼的包裝。在根本上,沒有什麼區別。任務只是簡化線程管理,並且由於減少了樣板噪聲,它們通常更具表現力。

+0

克里斯,你可以解釋關於任務的計劃嗎? – Yanshof 2012-02-29 04:28:08

+1

我會添加一個答案,但我也會直接給你@ AdamMihalcin的回答 – 2012-02-29 04:33:27

+0

@ChrisShain我同意任務是在線程上安排的,並沒有試圖暗示線程與任務相同,但是相同的開發目標完成。也許我的解釋有點過於籠統...... – 2012-02-29 04:45:03

8

線程已經是v1.0的一部分,任務在.NET 4.0中發佈的Task Parallel Library TPL中引入。

您可以將任務視爲線程的更復雜版本。它們非常易於使用,並且與Threads相比具有很多優勢,如下所示:

  1. 您可以爲任務創建返回類型,就好像它們是函數一樣。
  2. 您可以使用「ContinueWith」方法,該方法將等待上一個任務,然後開始執行。 (抽象等)
  3. 摘要鎖應根據我公司的指導方針來避免。
  4. 您可以使用Task.WaitAll並傳遞一組任務,以便您可以等待所有任務完成。
  5. 您可以將任務附加到父任務,因此您可以決定父項還是子項將首先存在。
  6. 您可以使用LINQ查詢實現數據並行性。
  7. 您可以創建並行和foreach循環
  8. 非常容易處理異常與任務。
  9. *最重要的是,如果相同的代碼在單核機器上運行,它將充當單個進程而沒有任何線程開銷。

任務的缺點在螺紋:

  1. 你需要誰學到的操作系統能夠理解線程更好的.NET 4.0
  2. 新人。
  3. 新的框架,所以沒有太多的援助可用。

一些提示: - 總是使用Task.Factory.StartNew方法,它在語義上是完美的和標準的。

看看任務並行Libray瞭解更多信息 http://msdn.microsoft.com/en-us/library/dd460717.aspx

3

擴大對埃裏克利珀評論:

Thread s爲的方式,讓您的應用程序做幾件事情並列。例如,您的應用程序可能有一個線程處理來自用戶的事件,例如按鈕點擊,另一個線程執行一些長時間的計算。這樣,你可以同時做兩件不同的事情。如果你沒有這樣做,用戶將不會點擊按鈕,直到計算完成。所以,Thread是可以執行你寫的一些代碼的東西。

Task另一方面表示某個工作的抽象概念。這項工作可能會產生結果,並且您可以等到作業完成後(通過撥打Wait())或在完成作業後說您想做某些事情(通過致電ContinueWith())。

您想要表示的最常見的工作是與當前代碼並行執行一些計算。而Task爲您提供了一個簡單的方法來做到這一點。代碼實際運行的方式和時間由TaskScheduler定義。默認的使用ThreadPool:一組可以運行任何代碼的線程。這是因爲創建和切換效率低下的線程。

但是Task不必直接與某些代碼關聯。您可以使用TaskCompletionSource創建Task,然後根據需要設置其結果。例如,您可以創建一個Task,並在用戶單擊按鈕時將其標記爲已完成。其他一些代碼可能會在Task上等待,並且在等待時,沒有執行該代碼Task

如果你想知道什麼時候使用Task以及何時使用ThreadTask更容易使用和更高效,創建自己的Thread秒。但有時候,你需要比Task提供更多的控制。在這些情況下,直接使用Thread是有意義的。

相關問題