2010-09-17 23 views
3

我有一個Backgroundworker,其目的是在後臺順序運行作業。現在一個工作是以多線程的方式實現的。這意味着,Backgroundworker將創建多個線程。我使用任務並行庫,所以我使用Task.Factory.StartNew創建多個任務。Backgroundworker和TPL的任務有相同的ManagedThreadID?

任務運行後,Backgroundworker等待所有這些完成。

現在我打印Backgroundworker的ManagedThreadID和所有任務的ManagedThreadIDs。我發現BackgroundWorker的ManagedThreadID始終與第一個任務的ManagedThreadID相同。我認爲這不應該發生,所以我不能解釋。我認爲Backgroundworker的線程必須與其創建的所有任務不同,因此ManagedThreadID必須完全不同。

任何人都可以解釋爲什麼這種情況發生?非常感謝你。

編輯:

的代碼與此類似:

Backgroundworker.Run(){ 
    // Print Thread.CurrentThread.ManagedThreadID. 
    var task = Task.Factory.StartNew(action1); // action1, action2 also print ManagedThredID. 
    taskList.Add(task); 
    task = Task.Factory.StartNew(action2); 
    taskList.Add(task); 
    ... // Several other tasks. 

    foreach(var task in taskList) task.Wait(); 
} 

你會發現,一個任務具有相同的ManagedThreadID爲BackgroundWorker的。

+2

請發佈您的代碼.... – 2010-09-17 12:06:36

回答

5

我會在這裏一瘸一拐地猜測TPL足夠聰明,可重用BackgroundWorker線程。由於工作者等待所有任務完成,在同一個線程中運行一個任務可能是一個優化。

從進一步調查,你所看到的是Task.Wait方法的預期行爲的結果。您可以在Parallel Programming Team博客的Task.Wait and "Inlining"上閱讀更多內容。

如果任務正在對已經 已經開始執行Wait'd,等待有 塊。但是,如果它沒有啓動 執行,Wait可能會將 目標任務從其排隊的調度程序 中拉出並在當前線程上內聯執行 。

2

後臺工作者從線程池以及TPL中繪製線程。可能發生的情況是後臺工作器啓動,它從池中提取線程並觸發TPL線程並立即將線程返回到池中。在TPL執行第一個任務時,TPL從池中抽取一個線程,並且它發生了與後臺工作人員曾經使用過的線程相同的線程。

當然,這只是一個假設,因爲你沒有顯示你的代碼而無法驗證。

+0

但是,OP提到工作人員明確地等待所有任務完成。 – 2010-09-17 12:08:44

+0

@João:當你等待別的東西可以使用你的線程。 – 2010-09-17 12:20:24

+0

@亨克霍爾特曼,我的疑惑與真正成爲別人的可能性或只是其中一項任務有關。這是一個優化的問題,如果它在TPL中,則線程不會返回到池中,而是由於調用「Wait」而內聯任務執行。基本上我並不完全同意工作線程返回池的聲明。 – 2010-09-17 13:42:16

2

你遇到的問題當然不是一個問題,而是一個功能(優化):TPL儘可能地重新使用線程。

當您創建一個任務時,它不會立即/永久地與一個線程關聯。任務是放入隊列中的作業,並且隊列由工作線程提供服務。因此,它可能是對BGW任務掛起,它的線程返回到池中,或者更直接也可能被等待()來完成:

// thread A 
var t1 = Task.Startnew(...); 
var t2 = Task.Startnew(...); 
t1.Wait(); // Thread A is idle/available so Wait can execute t1 
t2.Wait(); 
1

使用TaskCreationOptions.LongRunning以避免重新循環的後臺工作。

相關問題