我遇到麻烦了。我正在尝试使用 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();
}
这段代码由主例程执行。实际上,我有一个内核类列表,它们在单独的线程中运行,这些线程处理用于在 OpenGL 中呈现的表单。我需要使用屏障来同步所有内核线程,这非常有效。 当然,我需要在主线程(Main routine)中为创建的每个 Form 处理 Form 消息,实际上我调用 Application.DoEvents() 来完成这项工作。
现在我必须修改上面的代码片段以获得一个通用表单(简单对话框),而不会像 Application.Run 那样消耗 100% 的 CPU 调用 Application.DoEvents()。
目标应该是让上面的代码片段在到达时处理消息,并仅在必要时发出渲染(释放屏障),而不是试图获得最大 FPS;应该有可能切换到严格循环以尽可能多地渲染。
这怎么可能?
注意:上面的代码片段必须在主例程中执行,因为 OpenGL 上下文是在主线程上创建的。在单独的线程中移动代码片段并调用 Application.Run 非常不稳定且存在错误...
最佳答案
在循环中调用 Application.DoEvents() 没有任何根本性的错误。这就是 Form.ShowDialog() 所做的。它采取对策来确保用户不会遇到麻烦:它会禁用除对话框之外的所有窗口,因此用户无法退出应用程序或再次启动对话框。
您需要创建自己的,设置一个全局标志,指示您的主窗口已关闭,这样本地毯从您身下拉出时,您可以立即退出循环而无需调用任何更多代码。
您需要放弃处理器以避免 100% 的 CPU 负载。最简单的方法是调用 Thread.Sleep(1)。在 this thread 中查看我的答案举个例子。
关于c# - "Emulating"Application.Run 使用 Application.DoEvents,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2547277/