C# 等待 ThreadPool 中的所有线程终止
我有一个主线程和许多其他后台线程。
这些后台线程的主要用途是查询数据(许多查询来自网络,这就是我创建多个线程的原因:以避免用户界面滞后)。
当涉及到在主线程(用户界面)中导出数据时,我需要等到所有其他线程完成。
我的代码是:
//...code to open save file dialog...
//this loop is to wait for all the threads finish their query
//QueryThread.threadCount is the count of the background threads
while (QueryThread.threadCount != 0)
{
Thread.CurrentThread.Join(1000);
Console.WriteLine(QueryThread.threadCount);
}
//...code to export data...
如果我注释掉 while 循环,程序将顺利运行,但我导出的一些数据将有可能显示一些“不需要的”材料,因为某些后台线程尚未完成其工作。
然而,上面的 while 循环是无限的,threadCount 永远不会改变,这意味着在“Join()”方法期间,没有后台线程在运行。
为什么后台线程被阻塞以及如何解决该问题?
多谢!
I have one main thread, and many other background threads.
The main usage of those background threads is to query data (many queries from the web, which is why I create multiple threads: to avoid the lagging the user interface).
When it comes to exporting the data in the main thread (the user interface), I need to wait until all the other threads are finished.
My code is:
//...code to open save file dialog...
//this loop is to wait for all the threads finish their query
//QueryThread.threadCount is the count of the background threads
while (QueryThread.threadCount != 0)
{
Thread.CurrentThread.Join(1000);
Console.WriteLine(QueryThread.threadCount);
}
//...code to export data...
If I comment the while loop out, the program will run smoothly, but some of my exported data will have possibility of showing some "unwanted" material since some of the background threads haven't finished their work.
However, the above while loop is infinite, the threadCount never changes, which means during the "Join()" method, no background thread is running.
Why are the background threads blocked and how can I solve the problem?
Thanks a lot!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
您正在当前线程上调用 Join 方法,但该方法不会很有意义。您应该在工作线程上调用它:
不幸的是,这种方式违背了使用线程的目的,因为它将阻止调用,直到所有其他线程完成为止。
的 RunWorkerCompleted 事件BackgroundWorker
可用于通知后台任务完成并在表单上执行更新。You are calling the Join method on the current thread which doesn't make much sense. You should call it on your worker threads:
Unfortunately this kind of defeats the purpose of using threads because it will block the calling until all other threads are finished.
The RunWorkerCompleted event of a
BackgroundWorker
could be used to notify the completion of a background task and perform updates on the form.您的实现是错误的,您不应该使用 Join 作为线程之间的同步原语。
您应该做的是实现生产者-消费者模式。这将允许您让线程等待执行工作,然后当您将其放入队列时,线程会活跃起来执行该工作。
但是,我要做的更改是,从 UI 线程中,不要将数据直接添加到生产者和消费者共享的队列中。相反,制作该数据的副本,然后将该放入队列中。
有关如何在 .NET 中实现生产者-消费者模式的更多信息,我建议您阅读标题为“如何:同步生产者线程和消费者线程(C# 编程指南)"
Your implementation is wrong, and you shouldn't use Join as a synchronization primitive between your threads.
What you should do is implement the producer-consumer pattern. This will allow you to have the threads waiting to do work, and then come alive to do that work when you place it in the queue.
However, the change that I would make is that from the UI thread, don't add the data directly to the queue that the producer and consumer share. Rather, make a copy of that data and then put that in the queue.
For more information on how to implement the producer-consumer pattern in .NET, I suggest you read the MSDN documentation titled "How to: Synchronize a Producer and a Consumer Thread (C# Programming Guide)"
我想你想研究一下信号。为您的线程提供信号(ManualResetEvent/AutoResetEvent)。完成后,在工作线程中 Set() 关联的信号句柄。在主线程中执行“WaitAll(signal1, signal2,signal3)”来等待工作线程完成。
希望这有帮助,
I think you want to look into signalling. Have signals (ManualResetEvent/AutoResetEvent) for your threads. Set() the associated signal handle in the worker thread when it´s done. In the main thread do a `WaitAll(signal1, signal2,signal3)´ to wait for the completion of your worker threads.
Hope this helps,
我忍不住自己尝试一些。我确信还有改进的空间,但我认为它展示了如何处理一些多线程问题,包括原始问题。
Form.cs
Form.Designer.cs
希望这有帮助,
I couldn´t resist trying some myself. I´m sure there´s room for improvement but i think it shows how to deal with some multi threading issues, including the original question.
Form.cs
Form.Designer.cs
Hope this helps,
我通过改变生产者-消费者模型的方法解决了这个问题。
谢谢大家。
请查看此链接(由casperOne 上面),但要小心不要遵循微软的实施......
Go 这里 相反会给你一个更好的答案。
当然我做了一些改变,在我的例子中队列的类型是Delegate。
当主线程需要查询时,通过调用Enqueue(Delegate item)将委托指向进行查询的函数入队。这会将委托添加到生产者的“私有”队列中。
生产者会在适当的场合将自己队列中的项目添加到共享队列中(例如msdn示例中生成随机数并将其放入共享队列中)。
消费者使代表出队并运行它们。
感谢大家的帮助。 =]
I solved the problem by changing my approach to Producer-Consumer model.
Thanks all.
Please look at this link (provided by casperOne above), but be caution don't follow the implementation of microsoft....
Go here instead will give you a better answer.
Of course I've made some changes, the type of the Queue is Delegate in my case.
When a query is needed in the main thread, enqueue a delegate points to the function that makes query by calling the Enqueue(Delegate item). This add a delegate to the "private" queue of the Producer.
The producer will add the items in its own queue to the shared queue on the suitable occasion (like generating random number and put it into the shared queue in the msdn example).
The consumer dequeue the delegates and run them.
Thanks all for helping. =]