首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用于虚拟线程的队列

用于虚拟线程的队列
EN

Stack Overflow用户
提问于 2009-04-28 00:56:33
回答 8查看 3.1K关注 0票数 6

我认为这是一个非常常见的线程处理场景:

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

如果假设每个作业在他完成时都会触发一个事件(我正在使用BackgroundWorker类),我可以想出几种方法来完成这个任务,但我不知道什么是“正确”的解决方案。我希望你们中的一些专家能为我指明正确的方向。

解决方案1:在Main()函数中有一个while(继续){ Threading.Sleep(1000);}循环。Job_Completed事件处理程序中的代码将设置= false,当A)没有待排队的作业时,B)将所有排队的作业都完成。我以前使用过这个解决方案,虽然它似乎有效,但fine...it对我来说似乎有点“奇怪”。

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

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

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

我认为我在这里的最大困惑是,我不太明白事件是如何从我的Main()函数中触发的。很明显,他们是这样做的,我只是不明白从Windows消息循环的角度来看它的机制。解决这个问题的正确方法是什么?为什么?

EN

回答 8

Stack Overflow用户

发布于 2009-04-28 02:56:19

即使其他的答案很好,如果你想要另一个选择(你永远没有足够的选择),那么这作为一个想法怎么样?

只需将每个作业的数据放入FIFO堆栈中的结构中即可。

创建15个线程。

每个线程将从堆栈中获得下一个作业,并将其弹出。

当线程完成处理时,获得下一个作业,如果堆栈为空,则线程将死或只是休眠,等待。

唯一的复杂性,这是相当简单的解决,是让弹出在一个关键的部分(同步读取/pop)。

票数 3
EN

Stack Overflow用户

发布于 2009-04-28 01:09:52

Re:“不知何故,等待他们全部完成”

ManualResetEvent是您的朋友,在开始您的大批处理之前,创建这些小狗之一,在您的主线程中等待它,在工作完成后将其设置在后台操作的末尾。

另一个选项是手动创建线程并执行foreach线程thread.Join()

你可以用这个(我在测试期间用这个)

代码语言:javascript
复制
     private void Repeat(int times, int asyncThreads, Action action, Action done) {
        if (asyncThreads > 0) {

            var threads = new List<Thread>();

            for (int i = 0; i < asyncThreads; i++) {

                int iterations = times / asyncThreads; 
                if (i == 0) {
                    iterations += times % asyncThreads;                    
                }

                Thread thread = new Thread(new ThreadStart(() => Repeat(iterations, 0, action, null)));
                thread.Start();
                threads.Add(thread);
            }

            foreach (var thread in threads) {
                thread.Join();
            }

        } else {
            for (int i = 0; i < times; i++) {
                action();
            }
        }
        if (done != null) {
            done();
        }
    }

用法:

代码语言:javascript
复制
// Do something 100 times in 15 background threads, wait for them all to finish.
Repeat(100, 15, DoSomething, null)
票数 2
EN

Stack Overflow用户

发布于 2009-04-28 01:09:58

我只想使用任务并行库。

您可以使用您的任务作为一个简单的Parallel.For循环来完成这一任务,并且它将自动非常干净地管理这一过程。如果您不能等待C# 4和微软的实现,一个临时的解决办法就是编译和使用TPL的单点实现。(我个人更喜欢MS实现,尤其是较新的beta版本,但Mono在今天是功能性的和可再发行的。)

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/795842

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档