2014-01-07 146 views
1

我有一個基於表單的應用程序。 UI由線程處理。 從UI線程創建3個線程來執行一些處理。在C中同步線程#

Thread t1 = new Thread(() => performprocessing()); 
Thread t2 = new Thread(() => performprocessing()); 
Thread t3 = new Thread(() => performprocessing()); 

現在,我想在UI線程執行語句後,所有的3個線程完成他們的execution.So,我做了以下內容:

do 
{ 

} while (t1.IsAlive || t2.IsAlive || t3.IsAlive); 
/*--execute statement---*/ 

但我想用戶界面保持響應以及。在這種情況下,UI線程停留在循環中,直到所有三個線程完成執行。 如何執行此操作?

我讀了關於手動和自動重置事件,但我不知道如何在這種情況下使用它們。 請親引導我。

回答

5

嘗試使用Barrier

您需要將Barrier實例傳入您的線程,然後在線程中使用Barrier.SignalAndWait()。指定需要在Barrier的構造函數中繼續執行的信號數量。

一旦收到所有信號,正在等待的線程將停止阻塞。

0

使用後臺工作線程,您可以保持ui響應併發送進度。

void Form1_Load(object sender, EventArgs e) 
     { 
      BackgroundWorker b1 = new BackgroundWorker(); 
      BackgroundWorker b2 = new BackgroundWorker(); 
      BackgroundWorker b3 = new BackgroundWorker(); 
      b1.RunWorkerCompleted += b1_RunWorkerCompleted; 
      b2.RunWorkerCompleted += b2_RunWorkerCompleted; 
      b3.RunWorkerCompleted += b3_RunWorkerCompleted; 
     } 

     void b1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
     { 
     } 

     void b2_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
     { 
     } 

     void b3_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
     { 
     } 
+0

請不要使用它。你的'if(workerCompleted == 3)'不是線程安全的。在這裏有可能發生關係之前的關係。請記住,OP沒有給出線程將如何使用的上下文,只是他有一個UI線程和3個獨立的工作線程。 –

+0

回答更新以消除線程問題並使其更通用,謝謝@ dan-pantry – Marko

2

產生新線程是一種不好的做法,請改用線程池。

{ 
    var t1 = Task.Run(() => doSomething1()); 
    var t2 = Task.Run(() => doSomething2()); 
    var t3 = Task.Run(() => doSomething3()); 

    Task.WhenAll(t1, t2, t3).ContinueWith(t => doSomething4()); 
} 

.NET 4.5的更簡潔的方法是使用async/await。

async void Form1_Load(object sender, EventArgs e) 
{ 
    var t1 = Task.Run(() => doSomething1()); 
    var t2 = Task.Run(() => doSomething2()); 
    var t3 = Task.Run(() => doSomething3()); 

    await Task.WhenAll(t1, t2, t3); 
    doSomething4(); 
} 

.NET 4.0沒有定義Task.Run()和Task.WhenAll(),而是使用Task.Factory。

{ 
    var t1 = Task.Factory.StartNew(() => doSomething1()); 
    var t2 = Task.Factory.StartNew(() => doSomething2()); 
    var t3 = Task.Factory.StartNew(() => doSomething3()); 

    Task.Factory.ContinueWhenAll(new[] { t1, t2, t3}, tasks => doSomething4()); 
} 
+0

.Net 4.0沒有Task.Run()方法。我必須用Task.Factory.StartNew()和Task.Factory.ContinueWhenAll()方法來做到這一點。 – Kaushik

+0

'Task.Start()'? https://gist.github.com/DanPantry/8296168摘錄自我當前使用4.0中的任務的項目 –

+0

@Kaushik在涵蓋.NET 4.0的答案中添加了註釋。 –

-1

如果出於某種原因你不希望使用任務由solmaks提到的,那麼你可以使用Join()方法,將阻塞,直到該線程完成。

Thread t1 = new Thread(() => performprocessing()); 
Thread t2 = new Thread(() => performprocessing()); 
Thread t3 = new Thread(() => performprocessing()); 

t1.Join(); 
t2.Join(); 
t3.Join(); 

我不會推薦在UI線程中使用它,但它可能會導致您的應用程序無法響應。

+0

這會阻止UI線程。這裏的要點是保持UI的響應。 – Servy