是否可以在控制台应用中的“主”线程上运行异步回调

本文关键字:线程 运行 回调 异步 控制台 应用 是否 | 更新日期: 2023-09-27 18:36:37

在GUI应用程序中,有很多方法可以运行异步代码并使结果在"主"线程上运行:

  • 使用async/await
  • 使用BackgroundWorker
  • someControl.Invoke()
  • .ContinueWith(..., TaskScheduler.FromCurrentSynchronizationContext())

等等。

但是,这些选项在控制台应用程序中都不起作用,因为没有同步上下文或 GUI 运行循环。

我正在修改一个控制台项目,该项目有自己的手动运行循环。 像这样:

while (!cancelled)
{
    if(api.HasMessage())
    {
        api.HandleMessage();
    }
    Thread.Sleep(1);
}

我希望能够在这个项目中发出异步 Web 请求,同时仍然在主运行循环线程上处理结果以避免典型的多线程问题。 当然,我可以使用队列手动执行此操作,但是能够使用async/await或其他处理得更好的范例之一会很好。

有没有我可以从运行循环中调用的方法来实现这一点? 我在想象类似的东西,比如说,Thread.ResolveCurrentAwaitingTasks().

是否可以在控制台应用中的“主”线程上运行异步回调

这并不像调用方法那么容易,因为async延续被调度到SynchronizationContextTaskScheduler,而不是线程。所以,你必须写其中之一 - 不是一个非常有趣的前景。

你可以使用我写的一个名为AsyncContextSynchronizationContext;正常用法是这样的:

AsyncContext.Run(() =>
{
  while (!cancelled)
  {
    if(api.hasMessage())
    {
      api.handleMessage();
    }
    Thread.Sleep(1);
  }
});

这适用于async代码:

AsyncContext.Run(async () =>
{
  while (!cancelled)
  {
    if(api.hasMessage())
    {
      await api.handleMessageAsync();
    }
    Thread.Sleep(1);
  }
});

虽然我必须说Thread.Sleep有点黑客。我会考虑使用事件或其他类型的消息到达通知,例如 await api.GetNextMessageAsync() .