线程队列为假人

Cas*_*Gay 6 c# queue multithreading

我有我认为是一个非常常见的线程场景:

  • 我有100个相同的工作要完成
  • 所有工作都是相互独立的
  • 我想一次最多处理15个工作
  • 每个作业完成后,将开始新作业,直到所有作业完成

如果你假设每个作业在他完成时会触发一个事件(我正在使用BackgroundWorker类),我可以想出几种方法来解决这个问题,但我不确定"正确"的解决方案是什么.我希望你们中的一些大师可以指出我正确的方向.

解决方案1: 有一段时间(继续){Threading.Sleep(1000); }循环在我的main()函数.当A)没有任何作业要排队并且B)所有排队的作业都已完成时,Job_Completed事件处理程序中的代码将设置continue = false .我之前和之前都使用过这个解决方案似乎工作得很好......对我来说似乎有些"奇怪".

解决方案2: 在Main()函数中使用Application.Run().类似地,Job_Completed事件处理程序中的代码将在A)没有要排队的作业和B)所有排队的作业完成时调用Application.Exit().

解决方案3: 使用ThreadPool,排队所有500-1000个请求,让它们一次运行10个(SetMaxThreads)并以某种方式等待它们全部完成.

在所有这些解决方案中,基本思想是每次完成另一项工作时都会启动新工作,直到没有工作.因此,问题不仅在于等待现有作业完成,而且还要等到没有任何待处理作业开始.如果ThreadPool是正确的解决方案,那么等待ThreadPool完成所有排队项目的正确方法是什么?

我认为我最重要的困惑是我不明白我的Main()函数中是否能触发事件.显然他们这样做,我只是从Windows消息循环的角度来理解它的机制.解决这个问题的正确方法是什么,为什么?

mqp*_*mqp 0

这是我如何处理它的伪代码(这不利用 ThreadPool,所以有人可能有更好的答案:)

main
{
    create queue of 100 jobs
    create new array of 15 threads
    start threads, passing each the job queue
    do whatever until threads are done
}

thread(queue)
{
    while(queue isn't empty)
    {
        lock(queue) { if queue still isn't empty dequeue a thing }
        process the thing
    }

    queue is empty so exit thread
}
Run Code Online (Sandbox Code Playgroud)

编辑:如果您的问题是如何判断线程何时完成,并且您使用的是普通 C# 线程(不是 ThreadPooled 线程),您可以在每个线程上调用 Thread.Join() 并设置可选超时,并且它只会返回一次线程完成了。如果您想跟踪完成了多少个线程而不被一个线程挂起,您可以通过以下方式循环它们:

for(int i = 0; allThreads.Count > 0; i++)
{
    var thisThread = allThreads[i % threads.Count];
    if(thisThread.Join(timeout)) // something low, maybe 100 ms or something
        allThreads.Remove(thisThread);
}
Run Code Online (Sandbox Code Playgroud)