모든 백그라운드 스레드 풀 스레드가 완료되면 알림을 받습니다.

StackOverflow https://stackoverflow.com/questions/358721

  •  21-08-2019
  •  | 
  •  

문제

ThreadPool을 사용하여 3..10 스레드를 시작할 때 시나리오가 있습니다.각 스레드는 해당 작업을 수행하고 ThreadPool로 돌아갑니다.모든 백그라운드 스레드가 완료되면 메인 스레드에서 알림을 받을 수 있는 옵션은 무엇입니까?

현재 저는 생성된 각 스레드에 대해 변수를 증가시키고 백그라운드 스레드가 완료되려고 할 때 변수를 감소시키는 자체 개발 방법을 사용하고 있습니다.이것은 잘 작동하지만 더 나은 옵션이 있는지 궁금합니다.

도움이 되었습니까?

해결책

가변 (스레드 사이)을 감소시키는 것은 Interlocked.Decrement, 그러나 마지막 스레드가 있다면 (예 : 0이 될 때) 이벤트를 제기하면 그 접근 방식이 괜찮을 것입니다. 예외의 경우를 잃지 않도록 "마지막으로"블록에 있어야합니다 (또한 프로세스를 죽이고 싶지 않음).

"Parally Extensions"(또는 .NET 4.0)에서 Parallel.ForEach 여기 옵션 ... 모든 것이 블록으로 끝나는 또 다른 방법 일 수 있습니다. 모두 수동으로 볼 필요가 없습니다.

다른 팁

이 시도: https://bitbucket.org/nevdelap/poolguard

using (var poolGuard = new PoolGuard())
{
    for (int i = 0; i < ...
    {
        ThreadPool.QueueUserWorkItem(ChildThread, poolGuard);
    }
    // Do stuff.
    poolGuard.WaitOne();
    // Do stuff that required the child threads to have ended.

void ChildThread(object state)
{
    var poolGuard = state as PoolGuard;
    if (poolGuard.TryEnter())
    {
        try
        {
            // Do stuff.
        }
        finally
        {
            poolGuard.Exit();
        }
    }
}

여러 PoolGuard는 스레드가 종료된 시점을 추적하고 풀이 이미 닫혔을 때 시작되지 않은 스레드를 처리하기 위해 다양한 방법으로 사용할 수 있습니다.

64 개의 스레드가 대기하지 않으면 WaithAndle.waitall 메소드를 사용할 수 있습니다.

List<WaitHandle> events = new List<WaitHandle>();
for (int i = 0; i < 64; i++)
{
    ManualResetEvent mre = new ManualResetEvent(false);
    ThreadPool.QueueUserWorkItem(
        delegate(object o)
        {
            Thread.Sleep(TimeSpan.FromMinutes(1));
            ((ManualResetEvent)o).Set();
        },mre);
    events.Add(mre);
}
WaitHandle.WaitAll(events.ToArray());

실행은 모든 ManualReseteVents가 설정 될 때까지 대기합니다. 또는 WaitAny 메소드를 사용할 수 있습니다.

WaitAny 및 WaitAll 방법은 실행을 차단하지만 나중에 나중에 스레드가 수행되는지 결정하기 위해 스폰 된 작업에 링크 된 ManualReseteVents 사전을 사용하여 간단히 사용할 수 있습니다.

현재이 작업을 수행 할 수있는 내장 방법이 없습니다. 수영장 스레드 사용에 대한 가장 큰 고통 중 하나입니다.

Marc가 말했듯이, 이것은 평행 연장 / .NET 4.0으로 고정되는 종류입니다.

각 스레드에 독특한 수동으로 retetevent를 제공 할 수없고 완료되면 각 이벤트를 설정할 수 없습니다. 그런 다음 메인 스레드에서 전달 된 모든 이벤트를 기다릴 수 있습니다.

Marc의 솔루션은 모든 작업이 완료된시기를 알고 싶고 그보다 더 미세한 정보가 필요하지 않은 경우 (그렇듯이) 가장 좋습니다.

스폰 작업을 원하는 스레드와 다른 스레드가 알림을 받기 위해 다른 스레드를 원한다면 Waithandle을 사용할 수 있습니다. 코드가 훨씬 길다.

    int length = 10;
    ManualResetEvent[] waits = new ManualResetEvent[length];
    for ( int i = 0; i < length; i++ ) {
        waits[i] = new ManualResetEvent( false );
        ThreadPool.QueueUserWorkItem( (obj) => {
            try {

            } finally {
                waits[i].Set();
            }
        } );
    }

    for ( int i = 0; i < length; i++ ) {
        if ( !waits[i].WaitOne() )
            break;
    }

Waitone 방법은 쓰여진대로 항상 사실을 반환하지만, 일부 과부하가 인수로 시간을 초과한다는 것을 기억하도록하기 위해 그렇게 썼습니다.

세마포어를 사용하고 스레드 풀만큼 제한을 설정하는 것은 어떻습니까? 세마포어를 가져오고 스레드를 시작할 때 호출 할 수있는 방법을 가지고 스레드가 끝날 때 해제하고 모든 세마포어를 가져 오면 이벤트를 올리십시오.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top