2009-12-30 20 views
2

64 스레드 이상의 가능한 모든 스레드가 작업을 완료 할 때까지 기다릴 기본 스레드가 필요한 시나리오가 있습니다. 그 때문에 다음 도우미를 작성했습니다 유틸리티이 유틸리티 방법으로멀티 스레딩 - 모든 스레드가 신호를받을 때까지 기다림

public static void WaitAll(WaitHandle[] handles) 
    { 
     if (handles == null) 
      throw new ArgumentNullException("handles", 
       "WaitHandle[] handles was null"); 
     foreach (WaitHandle wh in handles) wh.WaitOne(); 
    } 

(WaitHandle.WaitAll()에서 64 WaitHandle이 한계를 회피하기 위해) 그 효과에 동기하므로, 그러나 각 WaitHandle이 단지 조사 배열의 모든 선행 한 ... 시그널링 한 후 , waithandles가 autoResetEvent wait 핸들 인 경우 작동하지 않습니다 (대기중인 스레드가 해제 되 자마자 지워짐)

이 문제를 해결하려면이 코드를 다음과 같이 변경하는 것을 고려하고 있지만 다른 사람들이 확인하여 작동하는지, 누군가가 문제를 보거나 더 나은 방법을 제안 할 수 있는지 확인하고 싶습니다. 사전에

감사 :

public static void WaitAllParallel(WaitHandle[] handles) 
    { 
     if (handles == null) 
      throw new ArgumentNullException("handles", 
       "WaitHandle[] handles was null"); 
     int actThreadCount = handles.Length; 
     object locker = new object(); 
     foreach (WaitHandle wh in handles) 
     { 
      WaitHandle qwH = wh; 
      ThreadPool.QueueUserWorkItem(
       delegate 
       { 
        try { qwH.WaitOne(); } 
        finally { lock(locker) --actThreadCount; } 
       }); 
     } 
     while (actThreadCount > 0) Thread.Sleep(80); 
    } 
+2

정말로 64 개 이상의 스레드가 필요합니까? 이것은 약간 IMHO 냄새. – dtb

+0

AutoResetEvent를 사용하는 방법과 이유를 더 자세히 설명 할 수 있습니까? 작업이 끝나면 스레드가 종료되지 않습니까? – dtb

+0

개체를 잠그는 대신 Interlocked (http://msdn.microsoft.com/en-us/library/system.threading.interlocked.aspx) 클래스를 사용하여 활성 작업자 수를 늘리거나 줄이는 것이 좋습니다. –

답변

-1
ThreadPool.QueueUserWorkItem(o => 
{ 
    try 
    { 
     using (var h = (o as WaitHandle)) 
     { 
      if (!h.WaitOne(100000)) 
      { 
       // Alert main thread of the timeout 
      } 
     } 
    } 
    finally 
    { 
     Interlocked.Decrement(ref actThreadCount); 
    } 
}, wh); 
+0

'qwH'는 루프에서 로컬로 선언되므로 문제가되지 않습니다. – dtb

2
나는 당신이하려는 정확히 모르겠어요

하지만 CountdownEvent (.NET 4.0) 개념적으로 문제를 해결할 것인가?

3

보유하고있는 스레드 수를 알고있는 경우 연동 감소를 사용할 수 있습니다.

{ 
eventDone = new AutoResetEvent(); 
totalCount = 128; 
for(0...128) {ThreadPool.QueueUserWorkItem(ThreadWorker, ...);} 
} 

void ThreadWorker(object state) 
try 
{ 
    ... work and more work 
} 
finally 
{ 
    int runningCount = Interlocked.Decrement(ref totalCount); 
    if (0 == runningCount) 
    { 
    // This is the last thread, notify the waiters 
    eventDone.Set(); 
    } 
} 

는 사실, 대부분의 시간은 심지어 신호를하지 않는 대신 콜백이 웨이터가 계속 곳에서 처리를 계속 호출이 내가 일반적으로 그것을 할 방법이다. 차단 된 스레드가 적고 확장 성이 뛰어납니다.

알고있는 것과 다를 수 있습니다 (예 : thoe 핸들 중 일부가 스레드가 아니고 I/O 또는 이벤트 인 경우 작동하지 않음). 그러나 이에 대해 생각해 볼 가치가 있습니다.

1

저는 C#이나 .NET 프로그래머가 아니지만 작업자 스레드 중 하나가 종료 될 때 게시되는 세마포어를 사용할 수 있습니다. 모니터링 스레드는 단순히 세마포어를 기다릴 것입니다. nn은 작업자 스레드 수입니다. 세마포어는 사용중인 리소스를 계산하는 데 전통적으로 사용되지만 n 번에 대해 동일한 세마포어를 대기하여 완료된 작업을 계산하는 데 사용할 수 있습니다.

0

많은 동시 스레드로 작업 할 때 스레드를 시작할 때 각 스레드의 ManagedThreadId를 사전에 추가 한 다음 각 스레드가 사전에서 죽어가는 스레드의 ID를 제거하는 콜백 루틴을 호출하도록하는 것이 좋습니다. Dictionary의 Count 속성은 활성 상태 인 스레드 수를 알려줍니다. 키/값 쌍의 값 측면을 사용하여 UI 스레드가 상태를보고하는 데 사용할 수있는 정보를 보유합니다. 사전을 자물쇠로 감싸 안전하게 보관하십시오.