2014-01-07 2 views
1

폼 기반 응용 프로그램이 있습니다. UI는 스레드에 의해 처리됩니다. UI 스레드에서 3 개의 스레드를 만들어 일부 처리를 수행합니다.C에서 스레드 동기화

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

지금, 나는 모든 3 개 스레드가 자신의 execution.So를 완료 한 후에는 UI 스레드에서 문을 실행하려면, 나는 다음과 같은 한 :

do 
{ 

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

하지만 난 UI가 반응을 유지하려면 게다가. 이 경우 UI 스레드는 모든 세 스레드가 실행을 완료 할 때까지 루프에 고정됩니다. 어떻게해야합니까?

수동 및 자동 재설정 이벤트에 대해 읽었지만 이러한 경우 사용 방법을 잘 모르겠습니다. 친절하게 안내해드립니다.

답변

5

Barrier을 사용해보세요.

스레드에 Barrier 인스턴스를 전달한 다음 스레드에서 Barrier.SignalAndWait()을 사용해야합니다. 배리어의 생성자에서 진행해야하는 신호의 수를 지정하십시오.

신호를 모두 받으면 대기중인 스레드가 차단을 중지합니다.

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

어떤 이유로 당신이 다음 스레드가 완료 될 때까지 차단됩니다 Join() 방법을 사용할 수 있습니다 solmaks에서 언급 한 바와 같이 작업을 사용하지 않으려면.

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