我有麻烦了。我正在尝试使用Application.DoEvents模拟call Application.Run ...这听起来很糟糕,然后我也接受了我的问题的替代解决方案...
我必须像Application.Run一样处理消息泵,但我需要在消息处理之前和之后执行代码。以下是主要的重要代码片段。
// Create barrier (multiple kernels synchronization)
sKernelBarrier = new KernelBarrier(sKernels.Count);
foreach (RenderKernel k in sKernels) {
// Create rendering contexts (one for each kernel)
k.CreateRenderContext();
// Start render kernel kernels
k.mThread = new Thread(RenderKernelMain);
k.mThread.Start(k);
}
while (sKernelBarrier.KernelCount > 0) {
// Wait untill all kernel loops has finished
sKernelBarrier.WaitKernelBarrier();
// Do application events
Application.DoEvents();
// Execute shared context services
foreach (RenderKernelContextService s in sContextServices)
s.Execute(sSharedContext);
// Next kernel render loop
sKernelBarrier.ReleaseKernelBarrier();
}这段代码由Main例程执行。实际上,我有一个内核类列表,它在单独的线程中运行,这些线程处理在OpenGL中呈现的表单。我需要使用一个屏障来同步所有的内核线程,这个方法工作得很好。当然,对于创建的每个表单,我都需要在主线程(Main例程)中处理表单消息,实际上我调用Application.DoEvents()来完成这项工作。
现在,我必须修改上面的代码片段,使其具有一个通用的表单(简单的对话框),而不像Application.Run那样占用调用Application.DoEvents()的100%的CPU。
目标应该是让上面的代码片段在消息到达时处理消息,并仅在必要时发出呈现(释放障碍),而不是试图获得最大FPS;应该有可能切换到严格循环以尽可能多地呈现。
这怎么可能呢?
注意:上面的代码片段必须在Main例程中执行,因为OpenGL上下文是在主线程上创建的。在单独的线程中移动代码片段并调用Application.Run是非常不稳定和有buggy的……
发布于 2010-03-31 02:18:16
在循环中调用Application.DoEvents()并没有什么本质上的错误。这就是Form.ShowDialog()所做的。它采取反措施来确保用户不会陷入麻烦:它禁用对话框以外的所有窗口,这样用户就不能退出应用程序或再次启动对话框。
你需要创建你自己的,设置一个全局标志,指示你的主窗口已经关闭,这样你就可以立即退出循环,而不需要调用更多的代码。
您需要让出处理器,以避免100%的CPU负载。最简单的方法是调用Thread.Sleep(1)。请查看我在this thread中的答案以获取示例。
发布于 2010-03-31 01:40:34
不要这样做--这个东西很复杂,我很确定你自己实现它只会遇到麻烦。
你不能使用Application.AddMessageFilter()来实现你需要的东西吗?
发布于 2010-03-31 01:55:29
如果要构建这样的消息循环,则应该对实际的Win32消息处理函数执行PInvoke操作(这就是Application.Run在幕后所做的所有工作--它有一个名为UnSafeNativeMethods的内部类,它映射了许多消息处理函数)。
如果您不需要在消息调用之间保持处理--换句话说,如果线程在不主动处理消息时休眠是安全的--那么从User32.dll绑定WaitMessage并将其放入如下循环中:
while (WaitMessage())
{
Application.DoEvents();
}如果你需要更多的帮助,请告诉我。我现在正在重新安装VS,否则我会发布一个示例应用程序,展示如何进行绑定和PInvoke。
https://stackoverflow.com/questions/2547277
复制相似问题