2010-02-05 14 views
4

여러 스레드를 사용하여 데이터 테이블의 행을 처리하는 메서드가 있고 모든 작업 항목을 대기열에 넣은 다음 메서드가 끝날 때까지 메서드가 끝나지 않은 채 모든 처리가 완료되었는지 확인합니다.ThreadPool.GetAvailableThreads가 작동하지 않는 이유는 무엇입니까?

개발 과정에서 문제가 없지만 테스트를 위해 서버 (64 비트)에 넣을 때 메서드의 끝에서 기다리지 않습니다. 메서드가 곧바로 종료되기 때문에 Thread.Sleep() 호출도하지 않는 것입니다.

메소드를 종료 한 후에도 데이터row를 계속 처리하지만, 원하는 것은 아닙니다.

아이디어가 있으십니까? 감사

Public Sub ProcessAll(ByVal collection As DataTable, ByVal processDelegate As WaitCallback) 
     Dim workItem As DataRow 
     Dim availableThreads As Integer 
     Dim completionPortThreads As Integer 


     ThreadPool.SetMaxThreads(MAX_THREADS, MAX_THREADS) 

     ' loop round processing each pending record adding them to the Thread Queue 
     For Each workItem In collection.Rows 
      ThreadPool.QueueUserWorkItem(processDelegate, workItem) 
     Next 

     ' The ThreadPool is a collection of background threads, thus we need to do something to stop the main thread from moving on 
     Do 
      Thread.Sleep(1000) 
      ThreadPool.GetAvailableThreads(availableThreads, completionPortThreads) 
      ' in the case that all threads are free (how we check all are complete) wait a few seconds just to make sure 
      If availableThreads = MAX_THREADS Then 
       Thread.Sleep(5000) 
       ThreadPool.GetAvailableThreads(availableThreads, completionPortThreads) 
      End If 
     Loop While availableThreads < MAX_THREADS 
End Sub 
+0

해결하려는 근본적인 문제는 무엇입니까? 예. * 왜 *이 코드가 있습니까? –

+0

정말 간단합니다. 개별적으로 처리해야하는 DB의 엔티티 목록이 있으며 처리 속도가 매우 빨라야합니다. –

답변

5

귀하는 모든 행이 완료 될 때까지 기다릴 이런 식으로 일을 할 수 없습니다.

대신 처리 코드에서 "이봐, 방금 끝낸 행"이라는 코드를 알려주는 알림 메서드를 사용해야합니다.

이렇게하면 처리 된 행 수를 더 쉽게 추적 할 수 있습니다.

방법 나는 그것을 할 것 :

  1. 대리인이 증가
  2. 사용 Interlocked.Increment 처리 된 얼마나 많은 추적 0으로 초기화 된 Int32 값을 추가,
  3. 카운터를 늘린 후 대리자에 이벤트 개체를 설정하십시오.
  4. 주 방법에서는 이벤트가 설정 될 때까지 기다렸다가 카운터를 검사합니다. 충분히 높지 않으면 다시 돌아와 다시 기다립니다.

즉. 다음과 같이 입력하십시오 :

private volatile Int32 _Processed = 0; 
private AutoResetEvent _RowProcessedEvent = new AutoResetEvent(false); 

... in your delegate: 
Interlocked.Increment(ref _Processed); 
_RowProcessedEvent.Set(); 

... in your main method: 
while (_Processed < collection.Rows.Count) 
{ 
    _RowProcessedEvent.WaitOne(Timeout.Infinite); 
} 

완료되면 이벤트 객체를 닫는 것을 잊지 마십시오.

+0

멋진 답변, 정말 고마워요. 다른 사용자를위한 부가 메모. WaitOne (Int32)은 .Net 3.5 SP1 –

+0

우수한 솔루션까지 도입되지 않았습니다. 고마워요 @ LasseV.Karlsen –

관련 문제