MsgWaitForMultipleObjects的C#等价物是什么?

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

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

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

谢谢。

编辑:似乎WaitHandler.WaitAny()可能实际上是在发送消息。 请参阅cbrumme关于 CLR中消息抽取的论文 。

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

您可以看到有关长时间运行的活动对象模式的这篇文章 (带有示例)。

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

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

这是我使用ManualResetEvent的地方 。

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

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

希望这可以帮助。