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

时间:2016-02-27 22:53:54

标签: c# multithreading async-await task-parallel-library console-application

在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()

1 个答案:

答案 0 :(得分:4)

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

您可以使用名为that I wroteSynchronizationContext AsyncContext;正常用法如下:

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有点hackish。我考虑使用事件或其他类型的邮件到达通知,例如await api.GetNextMessageAsync()