【问题标题】:How can I call an asynchronous method from WndProc?如何从 WndProc 调用异步方法?
【发布时间】:2018-11-19 23:11:06
【问题描述】:

我有一个程序,我使用自定义消息从WndProc 调用一些方法,如下所示:

protected override void WndProc(ref Message m)
{
    switch ((uint)m.Msg)
    {
        case WM_QUIT:
            Application.Exit();
            return;
        case WM_STARTOP:
            Context.TændNas();
            m.Result = new IntPtr(1);
            break;
    }
    base.WndProc(ref m);
}

现在我想让这些方法异步。 但是,我无法将 async 关键字添加到 WndProc 覆盖。

如果我将Context.TændNasAsync 设为async 方法,我如何从WndProc 调用它?

结论

我赞成@Hans Passant 的建议,创建一个async 事件处理程序。这样我就可以在 UI 线程上调用 async 方法,同时保持异步 (awaitable)。

【问题讨论】:

  • WndProc() 通常会引发事件以允许客户端代码响应消息。您也可以在此处执行此操作以获取异步 void 事件处理程序。当心consequences of such handlers
  • 您应该更新运行一些从消息处理功能中花费太多时间的东西。您只能启动一个任务,或创建一个后台工作线程,但不要阻塞 GUI 线程......这不是一个好主意,可能会导致无法预料的行为。
  • @julo,这不正确,Windows 窗体是基于消息的,即使长时间运行的任务也是通过例如按钮单击消息启动的。
  • @PoulBak:我知道这是可能的,但你不应该这样做。 GUI 将停止响应并可能导致混乱(对于用户),或者在最坏的情况下,操作系统可能会终止应用程序。 (应用程序 XY 没有响应。停止/关闭应用程序?- 窗口)

标签: c# async-await wndproc


【解决方案1】:

这应该可行:

Task.Run(()=>Context.TaendNas());

或者更确切地说:

Task.Run(async ()=> await Context.TaendNas());

【讨论】:

  • 那不是“一劳永逸”吗?
  • 您可以随时尝试在任务运行结束时添加 .Wait() 方法:Task.Run(...).Wait();但问题是如何从同步上下文运行异步方法
  • 无法使用此方法访问 UI 控件!
  • 当然可以。但要做到这一点,您必须确保您正在从 UI 线程访问 UI 控件。不是来自任何线程。您可以使用调用来完成。但这是完全不同的故事。
  • Task.Run 中包装同步方法在这里没有帮助,并且会以消费者无法处理的方式改变WndProc 的行为,即该方法将在完成之前返回。您的 secodn 示例也不起作用,因为 TaendNas 没有返回 Task 开头。
猜你喜欢
  • 1970-01-01
  • 2017-03-06
  • 2016-07-20
  • 1970-01-01
  • 2020-03-10
  • 2019-07-09
  • 2015-05-14
相关资源
最近更新 更多