2010-05-12 9 views
0

내 특정 시나리오 : - 주 스레드가 작업 스레드를 시작합니다.Monitor.Wait, Pulse - 작업자 스레드가 조건부로 실제 작업자 스레드로 동작해야하는 경우

wokerThread.Start(lockObj); 
lock(lockObj) 
Monitor.Wait(lockObj); 

어딘가에 - 는 작업자 스레드 중 하나가 완료 (재미 있은 예) 또는 작업자 스레드 자체가 내가 메인 스레드에서했던 그래서 뭐,

좋아에 가서 메인 스레드를 통보 할 때까지 메인 쓰레드 자체를 차단해야 또한

if(mainThreadShouldGoOn) 
lock(lockObj) 
    Monitor.Pulse(lockObj); 

, 작업자 스레드의 끝에 :

lock(lockObj) 
Monitor.Pulse(lockObj); 
작업자 스레드에서

지금까지 완벽하게 작동했습니다. 그러나 좋은 해결책입니까? 더 좋은가요?

편집 :

Monitor.Enter(lockObj); 
workerThread.Start(lockObj); 
Monitor.Wait(lockObj); 

그리고 노동자 다음과 같습니다 : 내가 메인 스레드에서이 같은 그것을 할 경우 무엇

void Worker(object lockObj) 
{ 
Monitor.Enter(lockObj); 
... 
... 
... 
if(mainThreadShouldGoOn) 
{ 
    Monitor.Pulse(lockObj); 
    Monitor.Exit(lockObj); 
} 
... 
... 
... 
if(!mainThreadShouldGoOn) 
{ 
    Monitor.Pulse(lockObj); 
    Monitor.Exit(lockObj); 
} 
} 

답변

0

왜 당신은 단지에 작업자 스레드를 시작합니까 바로 자러 가니? 메인 스레드에서 작업을 수행 할 수 있습니다.

하지만 당신은 그렇게 할 이유가 가정 ...

나는 당신의 솔루션을 개념적으로 괜찮다는 생각하지만, 문제가있을 수 있습니다. 주 스레드가 작업자를 시작한 후 잠금을 획득하기 전에 컨텍스트 전환이 발생하는 경우를 생각해보십시오. 그런 다음 작업자는 한 번에 신속하게 작업을 마칩니다. 이 경우 Wait 전에 Pulse이 호출되므로 나중에 주 스레드가 대기 모드에서 깨어나지 않습니다. 다음 그림이 있습니다.

class Program 
{ 
    static object theLock = new object(); 

    static void Main(string[] args) 
    { 
     Thread worker = new Thread(WorkerMain); 
     worker.Start(); 
     Thread.Sleep(1); 
     lock (theLock) 
     { 
      Monitor.Wait(theLock); 
     } 
     Console.WriteLine("Main done"); 
     Console.ReadLine(); 
    } 

    static void WorkerMain() 
    { 
     lock (theLock) 
     { 
      Monitor.Pulse(theLock); 
     } 
    } 
} 

대부분이 코드는 작동하지 않습니다. 잠금 범위에 worker.Start을 이동하여 문제를 해결할 수 있습니다.

예외적 인 경우에도주의해야 할 또 하나의 점은 Pulse입니다. 마침내 옳은 것을 사용하면 괜찮을 것입니다.

또는 항상 수행해야하는 작업과 if(mainThreadShouldGoOn) {...} 검사 후에 바로 수행되는 작업의 두 부분으로 작업자를 분리하는 것을 고려하십시오. 그런 다음 main에 의해 시작된 작업자 스레드에서 첫 번째 부분을 실행할 수 있고 필요한 경우 첫 번째 작업자에서 시작된 다른 작업자 스레드의 두 번째 부분을 실행할 수 있습니다. 그런 다음 Thread.Join()을 사용하여 첫 번째 작업자가 완료 될 때까지 기다릴 수 있습니다. 이렇게하면 약간의 성능 저하로 인해 동기화가 간단 해지고 오류 발생 가능성이 줄어 듭니다.

+0

안녕하세요, 자세한 답장을 보내 주셔서 감사합니다. 귀하의 제안에 조금을 기반으로, 나는 내 솔루션을 개정.내 원래 게시물의 편집을 참조하십시오. –

1

이 코드는 올바르지 않습니다. 작업자가 너무 빨리 완료되면 주 스레드를 영구적으로 차단할 위험이 있습니다. 여기에 사용할 적절한 동기화 객체는 ManualResetEvent (또는 auto, 중요하지 않음)입니다. 주 스레드의 Wait() 메서드를 호출하고 작업자의 Set() 메서드를 호출합니다. 스레드 풀 스레드 대신 스레드 인 한, Thread.Join()을 사용하면 마찬가지로 작동합니다.

+0

원본 게시물의 편집을 참조하십시오. –

관련 문제