有没有更好的方法来等待排队的线程?

Zan*_*oni 22 c# queue multithreading

有没有更好的方法在执行另一个进程之前等待排队的线程?

目前我在做:

this.workerLocker = new object(); // Global variable
this.RunningWorkers = arrayStrings.Length; // Global variable

// Initiate process

foreach (string someString in arrayStrings)
{
     ThreadPool.QueueUserWorkItem(this.DoSomething, someString);
     Thread.Sleep(100);
}

// Waiting execution for all queued threads
lock (this.workerLocker)  // Global variable (object)
{
     while (this.RunningWorkers > 0)
     {
          Monitor.Wait(this.workerLocker);
     }
}

// Do anything else    
Console.WriteLine("END");
Run Code Online (Sandbox Code Playgroud)
// Method DoSomething() definition
public void DoSomething(object data)
{
    // Do a slow process...
    .
    .
    .

    lock (this.workerLocker)
    {
        this.RunningWorkers--;
        Monitor.Pulse(this.workerLocker);
    }
}
Run Code Online (Sandbox Code Playgroud)

Ste*_*fen 14

您可能想要查看AutoResetEvent和ManualResetEvent.

这些都是针对这种情况的(在做"某事"之前等待ThreadPool线程完成).

你会做这样的事情:

static void Main(string[] args)
{
    List<ManualResetEvent> resetEvents = new List<ManualResetEvent>();
    foreach (var x in Enumerable.Range(1, WORKER_COUNT))
    {
        ManualResetEvent resetEvent = new ManualResetEvent();
        ThreadPool.QueueUserWorkItem(DoSomething, resetEvent);
        resetEvents.Add(resetEvent);
    }

    // wait for all ManualResetEvents
    WaitHandle.WaitAll(resetEvents.ToArray()); // You probably want to use an array instead of a List, a list was just easier for the example :-)
}

public static void DoSomething(object data)
{
    ManualResetEvent resetEvent = data as ManualResetEvent;

    // Do something

    resetEvent.Set();
}
Run Code Online (Sandbox Code Playgroud)

编辑:忘记提及你可以等待单个线程,任何线程等等.另外,根据您的情况,AutoResetEvent可以简化一些事情,因为它(顾名思义)可以自动发出事件信号:-)

  • 这样做不会有效,你可以更多地分解Windows上的64个项目只允许你等待多达64个句柄. (9认同)
  • 你忘了将`resetEvent`附加到`resetEvents`中. (2认同)

Mar*_*ell 13

怎么样ForkJoin使用只是Monitor;-p

Forker p = new Forker();
foreach (var obj in collection)
{
    var tmp = obj;
    p.Fork(delegate { DoSomeWork(tmp); });
}
p.Join();
Run Code Online (Sandbox Code Playgroud)

这个早期答案中显示的完整代码.

或者对于上限大小的生产者/消费者队列(线程安全等),这里.