【发布时间】:2015-10-13 08:23:42
【问题描述】:
在 Windows 应用程序开发的“旧时代”,使用 PostMessage Windows API 函数将消息发布到您自己的应用程序是一种将特定任务的处理移出当前堆栈上下文的好方法,同时保留在主线程,从而避免尝试在另一个线程上执行主线程任务的细微差别(这当然会导致使用 Invoke 样式方法将处理移回主线程等)
你所要做的就是:
- 使用大于 WM_USER 的数值创建自定义窗口消息
- 使用 PostMessage 向您自己广播该消息
- 向主对话窗口添加一个处理程序,以处理您的自定义 WM_* 消息的消息并对其执行操作
这使您可以将处理移出棘手的执行上下文,例如深入嵌套的调用堆栈中,可能使用持有资源锁的方法等,而是将处理延迟到“更干净”的执行上下文。
例如,我真的不喜欢在属性 setter/getter 中做很多事情,尤其是对于依赖属性,除了保存或恢复值。那和事件处理程序是执行上下文的两个主要示例,我想延迟与特定事件关联的任务并将其传递回主线程以在主线程执行的顶级执行上下文。
我想对我的 WPF/XAML 应用程序做同样的事情,但我只想使用托管代码,所以我不想使用 Windows API 调用,如果可能的话,所以我尽量避免做类似的事情显示在以下两个 SO 帖子中:
How to create C# Event to handle MFC Windows message from PostMessage()
What's the equivalent of PostMessage to self, for Windows Forms?
是否有与实现相同功能的 WPF/XAML 托管代码兼容的 C# 机制、习语等?。是否有 WPF/XAML 托管代码技术可以像 PostMessage 那样使用应用程序的输入队列?
注意,虽然我不是专家,但我已经多次使用 C# 的 Task.Run()、TaskFactory.StartNew()、Control.BeginInvoke()、async/await 等工具。正如我所说,我正在寻找一些希望不需要创建新线程或任何其他不寻常的编码体操的东西。
【问题讨论】:
-
“使用 PostMessage....是移动特定任务处理的好方法”——我对“伟大”这个词的使用提出异议在那里。请注意,
PostMessage()具有比这更广泛的功能;这种情况下的影响与任何事情一样都是副作用。但是,是的,这是人们实现这一目标的一种方式。 Winforms 等价物是Control.BeginInvoke()(您已经使用过),WPF 等价物是Dispatcher.BeginInvoke()。不过,Stack Overflow 确实不是这种 API 研究的最佳场所。首先要从 API 本身的文档开始。 -
+1。 PostMessage 之所以起作用,是因为您可以在等待某些东西时运行单独的消息泵,从而产生异步行为的错觉。问题当然是,一旦你有两件事在等待,那么你就有潜在的死锁情况。 Async/wait 是 C# 机制,旨在通过确保异步代码在稍后恢复之前立即返回来替代这一点并防止死锁。
标签: c# wpf xaml postmessage delayed-execution