gpt4 book ai didi

c++ - 非托管 C++ 中的 WinForm 样式 Invoke()

转载 作者:太空狗 更新时间:2023-10-29 21:08:40 24 4
gpt4 key购买 nike

我一直在玩 DataBus一个爱好项目的类型设计,我遇到了一个问题。后端组件需要通知 UI 发生了某些事情。我的总线实现与发送者同步传递消息。换句话说,当您调用 Send() 时,该方法会阻塞,直到所有处理程序都已调用。 (这允许调用者对事件对象使用堆栈内存管理。)

但是,请考虑事件处理程序更新 GUI 以响应事件的情况。如果调用处理程序,并且消息发送者在另一个线程上,则处理程序无法更新 GUI,因为 Win32 的 GUI 元素具有线程关联性。更多动态平台(如 .NET)允许您通过调用特殊的 Invoke() 方法将方法调用(和参数)移动到 UI 线程来处理此问题。我猜他们使用 .NET parking 窗口或类似的东西来做这些事情。

一种病态的好奇心诞生了:即使我们限制了问题的范围,我们能否在 C++ 中做到这一点?我们可以让它比现有的解决方案更好吗?我知道 Qt 使用 moveToThread() 函数做了类似的事情。

更好的是,我会特别提到我正在努力避免使用以下形式的代码:

if(! this->IsUIThread())
{
Invoke(MainWindowPresenter::OnTracksAdded, e);
return;
}

位于每个 UI 方法的顶部。在处理这个问题时,这种舞蹈在 WinForms 中很常见。我认为这种问题应该与特定于域的代码和用于处理它的包装对象隔离开来。

我的实现包括:

  • DeferredFunction - 将目标方法存储在 FastDelegate 中的仿函数, 并深度复制单个事件参数。这是跨线程边界发送的对象。

  • UIEventHandler - 负责从总线调度单个事件。当调用 Execute() 方法时,它会检查线程 ID。如果它与 UI 线程 ID(在构建时设置)不匹配,则会在堆上分配一个带有实例、方法和事件参数的 DeferredFunction。指向它的指针通过 PostThreadMessage() 发送到 UI 线程。

  • 最后,线程消息泵的 Hook 函数用于调用 DeferredFunction 并取消分配它。或者,我可以使用消息循环过滤器,因为我的 UI 框架 (WTL) 支持它们。

最终,这是一个好主意吗?整个消息 Hook 的事情让我怀疑。意图当然是崇高的,但是有什么我应该知道的陷阱吗?或者有更简单的方法吗?

最佳答案

我已经离开 Win32 游戏很长时间了,但我们过去实现这一目标的方法是使用 PostMessage 将 Windows 消息发布回 UI 线程,然后从那里处理调用,传递额外的wParam/lParam 中您需要的信息。

事实上,如果这就是 .NET 在 Control.Invoke 中处理此问题的方式,我不会感到惊讶。

更新:我是 currios,所以我检查了 reflector,这就是我的发现。

Control.Invoke 调用 MarshaledInvoke,后者执行大量检查等,但有趣的是对 RegisterWindowMessage 和 PostMessage 的调用。所以事情并没有太大改变:)

关于c++ - 非托管 C++ 中的 WinForm 样式 Invoke(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2626748/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com