2010-11-21 2 views
2

WaitHandle.WaitAll (waitHandles)을 사용하여 winForm을 차단하지 않고 WaitHandle.WaitAll의 신호를받을 때 실행되는 다른 스레드를 설정하면 안됩니까?C# 스레드, WaitHandle.WaitAll

+6

질문에 대한 대답을 받아 들여야합니다. – SLaks

답변

3

나는 WaitHandle.WaitAll을 사용하지 않을 것입니다. 이 접근 방식에는 몇 가지 문제점이 있습니다.

  • 핸들 제한은 64입니다.
  • STA 스레드에서는 사용할 수 없습니다.
  • 분명히 자원을 소비하는 복수 WaitHandle 인스턴스의 생성에 의존하는 패턴을 촉진합니다.

대신 여러 이벤트를 기다릴 때 일반적으로 CountdownEvent 클래스를 사용합니다. 자, 문제는 당신이 피하려고하는 바로 그 스레드에서 Wait으로 전화해야한다는 것입니다. 차단 호출을 피하기위한 표준 메커니즘은 ThreadPool.RegisterWaitForSingleObject 메서드를 사용하는 것입니다. 그러나 불행히도 WaitHandleCountdownEvent이 해당 클래스에서 상속받지 않습니다.

해결책은 ThreadPool.RegisterWaitForSingleObject 메서드에서 사용할 수있는 사용자 고유의 CountdownWaitHandle 클래스를 만드는 것입니다. 이 방법을 사용하면 WaitHandle이 신호를 받으면 실행될 콜백 대리자를 지정할 수 있습니다.

다음은 CountdownWaitHandle 클래스의 가장 기본적인 구현 방법입니다. 필요한 하딩 코드를 모두 직접 추가해야하지만 시작하면됩니다. 여기

public class CountdownWaitHandle : WaitHandle 
{ 
    private int m_Count = 0; 
    private ManualResetEvent m_Event = new ManualResetEvent(false); 

    public CountdownWaitHandle(int initialCount) 
    { 
     m_Count = initialCount; 
    } 

    public void AddCount() 
    { 
     Interlocked.Increment(ref m_Count); 
    } 

    public void Signal() 
    { 
     if (Interlocked.Decrement(ref m_Count) == 0) 
     { 
      m_Event.Set(); 
     } 
    } 

    public override bool WaitOne() 
    { 
     return m_Event.WaitOne(); 
    } 
} 

아이디어는 대신 다양한 WaitHandle 인스턴스를 사용하는 단일 CountdownWaitHandle 인스턴스를 사용한다는 것입니다. 원하는 카운트로 인스턴스를 초기화 한 다음 Signal으로 전화하여 카운트를 감소시킵니다. 카운트가 0이되면 WaitHandle은 신호 상태가됩니다. 따라서 복수 WaitHandle 인스턴스에서 Set을 호출하고 WaitHandle.WaitAll을 사용하여 차단하는 대신 을 호출하여이 인스턴스와 블록에서 Signal을 호출 할 수 있습니다. 다시 WaitHandle이 신호를 받으면 TheadPool.RegisterWaitForSingleObject을 사용하여 콜백을 호출하여 스레드 풀에 대한 차단 호출을 푸시 (push) 할 수 있습니다.

0

백그라운드 스레드에서 WaitAll으로 전화 한 다음 BeginInvoke을 호출하여 UI 스레드로 다시 이동할 수 있습니다.

+0

더 구체적 일 수 있습니까? – kosnkov

0

ManualResetEvent을 살펴보십시오. 이것을 사용하면 스레드가 완료되면 이벤트를 설정할 수 있고 다른 스레드는이 이벤트를 기다리거나 신호가있는 상태인지 확인할 수 있습니다.

ManualResetEvent ev = new ManualReserEvent(); 
while(Users["user428547"].AcceptanceRate == 0) 
{ 
    // this might take a long time 
}; 
ev.Set(); // done, he accepted an answer. 
0

아마 당신은 다른 스레드 자신을 시작하고 자신이 스레드에 WaitHandle.WaitAll를 호출 할 수 있을까? 너무 많은 다른 쓰레드를 시작하지 않는다면 정상적으로 작동 할 것입니다.

+0

no cos 그러면 STA 스레드에서 여러 핸들에 대해 WaitAll이 지원되지 않습니다. – kosnkov

+0

새 스레드를 MTA 스레드로 만들 수 없습니까? MSDN 소셜이 여기에 대한 토론이있는 것 같습니다. http://social.msdn.microsoft.com/Forums/en-US/netfxbcl/thread/eefc0160-987c-47e1-a41b-bbae96726ec4/ – dsolimano