3

我遇到麻烦了。我正在尝试使用 Application.DoEvents 模拟调用 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 中呈现的表单。我需要使用屏障来同步所有内核线程,这非常有效。当然,对于创建的每个 Form,我需要在主线程(Main 例程)中处理 Form 消息,实际上我调用 Application.DoEvents() 来完成这项工作。

现在我必须修改上面的代码片段以获得一个通用的表单(简单对话框),而不会像 Application.Run 那样消耗 100% 的 CPU 调用 Application.DoEvents()。

目标应该是让上面的代码片段在到达时处理消息,并仅在必要时发出渲染(释放屏障),而不是试图获得最大 FPS;应该有可能切换到严格循环以尽可能多地渲染。

怎么可能?

注意:上面的代码片段必须在 Main 例程中执行,因为 OpenGL 上下文是在主线程上创建的。在单独的线程中移动代码段并调用 Application.Run 非常不稳定和错误......

4

3 回答 3

1

在循环中调用 Application.DoEvents() 没有任何根本性的错误。这就是 Form.ShowDialog() 所做的。它采取对策以确保用户不会遇到麻烦:它禁用对话框以外的所有窗口,因此用户无法退出应用程序或再次启动对话框。

您需要创建自己的,设置一个全局标志,指示您的主窗口已关闭,这样您就可以在从您下方拉出地毯时立即退出循环而无需调用任何更多代码。

您需要让处理器来避免 100% 的 CPU 负载。最简单的方法是调用 Thread.Sleep(1)。查看我在此线程中的答案以获取示例。

于 2010-03-30T18:18:16.497 回答
1

不要这样做 - 这东西非常复杂,我敢肯定你自己实现它只会遇到麻烦。

你不能Application.AddMessageFilter()用来实现你所需要的吗?

于 2010-03-30T17:40:34.120 回答
0

如果你要构建一个像这样的消息循环,你应该 PInvoke 实际的 Win32 消息处理函数(这就是 Application.Run 在幕后所做的一切——它有一个名为 UnSafeNativeMethods 的内部类,它映射了一堆它们)。

如果您不需要在消息调用之间继续处理 - 换句话说,如果您的线程在不主动处理消息时休眠是安全的 - 然后从 User32.dll 绑定WaitMessage并将其放入循环中,如:

while (WaitMessage())
{
  Application.DoEvents();
}

如果您需要更多帮助,请告诉我。我现在正在重新安装 VS,或者我会发布一个示例应用程序,展示如何进行绑定和 PInvoke。

于 2010-03-30T17:55:28.617 回答