C# WPF/XAML应用程序的Windows API PostMessage到self的等价物?

C# WPF/XAML应用程序的Windows API PostMessage到self的等价物?,c#,wpf,xaml,postmessage,delayed-execution,C#,Wpf,Xaml,Postmessage,Delayed Execution,在Windows应用程序开发的“旧时代”,使用PostMessage Windows API函数将消息发布到您自己的应用程序是将特定任务的处理从当前堆栈上下文中移出的好方法,同时保留在主线程上,从而避免尝试在另一个线程上执行主线程任务的细微差别(这当然会导致使用Invoke样式的方法将处理移回主线程,等等) 你所要做的就是: 创建数值大于WM_USER的自定义windows消息 使用PostMessage向您自己广播该消息 将处理程序添加到主对话框窗口,以处理自定义WM_*消息的消息并对其执行

在Windows应用程序开发的“旧时代”,使用PostMessage Windows API函数将消息发布到您自己的应用程序是将特定任务的处理从当前堆栈上下文中移出的好方法,同时保留在主线程上,从而避免尝试在另一个线程上执行主线程任务的细微差别(这当然会导致使用Invoke样式的方法将处理移回主线程,等等)

你所要做的就是:

  • 创建数值大于WM_USER的自定义windows消息
  • 使用PostMessage向您自己广播该消息
  • 将处理程序添加到主对话框窗口,以处理自定义WM_*消息的消息并对其执行操作
这使您能够将处理从棘手的执行上下文中移出,比如深入嵌套的调用堆栈中,方法可能持有资源锁,等等,相反,将处理延迟到“更干净”的执行上下文中

例如,除了保存或还原值之外,我真的不喜欢在属性setter/getter中做很多事情,尤其是对于依赖性属性。这和事件处理程序是执行上下文的两个主要示例,我希望延迟与特定事件相关联的任务,并将其传递回要执行的主线程在主线程执行上下文的顶层执行

我想对我的WPF/XAML应用程序执行同样的操作,但我只想使用托管代码,因此如果可能的话,我不想使用Windows API调用,因此我试图避免执行以下两篇so文章中所述的操作:

是否有一种与WPF/XAML托管代码兼容的C#机制、习惯用法等可以实现相同的功能?是否有一种WPF/XAML托管代码技术可以像PostMessage一样利用应用程序的输入队列


请注意,尽管我不是专家,但我使用过C#的Task.Run()、TaskFactory.StartNew()、Control.BeginInvoke(),async/await等工具。正如我所说的,我正在寻找一些希望不需要创建新线程或任何其他不寻常的编码技巧的东西。

好吧,我建议从一开始就不要进入这种情况

但也就是说,您可以将
异步void
任务一起使用。Yield

async void DoSomethingAsync()
{
  await Task.Yield();
  // Code here will run directly off the message loop.
}
Task.Yield
将导致该方法立即返回,将该方法的其余部分排入消息循环的队列。
async void
将导致异常直接抛出到消息循环


好的,你做到了。我刚刚发布了一个答案,里面有
任务。Yield
async void
。Blech,现在我需要洗手了…

“使用PostMessage…是移动特定任务处理的一个很好的方式”——我对其中“great”一词的用法表示怀疑。注意
PostMessage()
的功能远不止于此;该场景中的效果与任何东西一样具有副作用。但是,是的,这是人们实现这一点的一种方式。Winforms等价物是
Control.BeginInvoke()
(您已经使用过),WPF等价物是
Dispatcher.BeginInvoke()
。不过,堆栈溢出确实不是此类API研究的最佳场所。首先要从API本身的文档开始。+1.PostMessage之所以有效,是因为您可以在等待某个内容时运行单独的消息泵,从而产生异步行为的错觉。当然,问题是,一旦您有了两个如果等待,则可能会出现死锁情况。Async/wait是一种C#机制,旨在通过确保异步代码在稍后恢复之前立即返回来替换此机制并防止死锁。如果从工作线程(而不是主线程)调用DoSomethingAsync(),则post-Yield()语句代码是否仍会在主线程上运行?“异步无效"是我心中的一根刺。我在你的网站上读了很多书,真的很明白为什么应该避免,特别是出于异常处理的原因。但在一些情况下,我发现自己在做一些真正痛苦的编码练习,试图避免它,并且总是放弃,无论如何都要这样做。事实上MS允许它用于事件德勒斯向我指出,尽管需要避免,但它有明确的用例。@RobertOschler:不。这只是一种跳转到当前上下文顶层的方法,因此如果在线程池线程上运行,
wait
之后的代码将在不同的线程池线程上执行。很明显,我不会允许在我的线程中使用这种代码总有更好的方法,可能是重新设计的一部分。