什么是MsgWaitForMultipleObjects的C#等价物?

时间:2010-02-21 23:36:27

标签: c# multithreading threadpool

我在报告模式下有一个带有ListView的Windows窗体。对于视图中的每个项目,我需要执行一个长时间运行的操作,其结果是一个数字。

我在本机win32中执行此操作的方法是为每个项创建一个工作线程(天真地;当然我不会创建无限数量的线程),然后在线程句柄数组上创建MsgWaitForMultipleObjects()。当每个计算完成时,线程信号和主UI线程唤醒并更新。与此同时,我们提取消息,以便UI线程保持响应。

任何人都可以提供一个如何在C#中运行的示例吗?我看过Monitor对象,它似乎不是我想要的 - 或者是否在阻塞时抽取消息?

感谢。

编辑:似乎WaitHandler.WaitAny()可能实际上是在发送消息。有关CLR中消息提取的信息,请参阅cbrumme's treatise

2 个答案:

答案 0 :(得分:2)

我认为,长期运行的活动对象是您的最佳选择。主线程调用代理(活动对象)。代理将调​​用方法转换为消息,此消息将转到队列。代理向未来对象返回调用者(它是对未来结果的引用)。调度程序逐个使消息出列,并在其他线程(工作线程)中重新执行您的任务。当工作线程完成一个任务时,它会更新未来对象的结果或调用回调方法(例如,更新你的UI).Dispather可以有许多工作线程来同时执行更多的任务。

您可以看到关于长时间运行的活动对象模式的 article (带示例)。

答案 1 :(得分:2)

让你的主线程创建一个经理线程。您可以使用BackgroundWorker来实现此目的。此管理器线程为ListView中的每个项启动工作线程。这将允许您的UI在后台线程处理时不会挂起而继续响应用户输入。

现在,问题是如何等待每个工作线程完成。不幸的是,我一直无法找到一种方法来获取System.Threading.Thread个对象的线程句柄。我不是说没有办法做到这一点;我还没找到一个。另一个复杂的方面是System.Threading.Thread类是密封的,所以我们无法从中得到某种“句柄”。

这是我使用ManualResetEvent的地方。

假设每个工作线程只是一个ThreadPool线程。管理BackgroundWorker为ListView中的每个项创建一个ManualResetEvent对象。当BackgroundWorker启动每个ThreadPool主题时,将ManualResetEvent作为参数传递给QueueUserWorkItem function。然后,在每个ThreadPool线程退出之前,设置ManualResetEvent对象。

BackgroundWorker线程然后可以将所有ManualResetEvent个对象放入一个数组中,并使用WaitHandle.WaitXXX functions等待该数组。每个线程完成后,您可以使用BackgroundWorker的事件来更新UI,或者您可以使用Control.Invoke()技术更新UI(请参阅Marc Gravell的回答here)。

希望这有帮助。