【问题标题】:Thread switch in async main c# 7.1异步主 c# 7.1 中的线程切换
【发布时间】:2018-08-11 22:01:04
【问题描述】:

我遇到了 c# 7.1 的异步主要功能的问题。

这里是一个演示问题的示例项目的 github 链接:https://github.com/xorpherion/CSharpAsyncMainProblem

代码用作游戏循环的一部分。如您所见,主要签名使用异步,因此在幕后创建了同步上下文。

Timedloop 类是一种在当前时间超过限制时尝试安排事件 (OnTick) 的计时器。触发事件的方法有 3 种:SpinLoop、WaitLoopAsync 和 WaitLoop。 SpinLoop 和 WaitLoop 的行为符合预期(OnTick 的单线程调度)。问题在于 WaitLoopAsync。我在这里期望的是也留在当前线程上,因为 .ConfigureAwait 未设置为“false”。但是当您运行代码时,您会在控制台上看到线程 ID 更改的消息。其他循环“类型”不会发生这种情况。

我的问题是:为什么没有在同一个线程上安排延续?

我在 .net core 2.1 上运行它。

【问题讨论】:

标签: c# async-await


【解决方案1】:

如您所见,主要签名使用异步,因此在幕后创建了一个同步上下文。

不,事实并非如此。等待任务将(默认情况下)使用同步上下文如果它从一个开始 - 但它不会自动创建一个。控制台应用程序通常没有任何同步上下文,因此继续在线程池线程上执行。

如果您希望控制台应用程序使用同步上下文,您需要自己创建一个。 Stephen Cleary 的AsyncEx project 包含一个实现;有关更多详细信息,请参阅this Stack Overflow answer

【讨论】:

  • 我专门使用了这个功能:blogs.msdn.microsoft.com/mazhou/2017/05/30/…,它的行为应该和你建议的不同,对吧?
  • @Nogiax:为什么会有不同的表现?正如博客文章所暗示的,异步Main 方法只是调用GetAwaiter().GetResult() 的语法糖。仍然没有什么可以为您隐式创建同步上下文。您可以通过记录 SynchronizationContext.Current 来验证这一点 - 我希望它在任何地方都为空。
  • 在 UI 应用程序中,await 是否确保方法在相同的 UI 上下文而不是相同的线程上恢复?
  • @variable:您需要在此处指定“UI 上下文”的含义以及确切的含义。
  • Windows 窗体应用 ui 和同步上下文
猜你喜欢
  • 2017-09-13
  • 2021-11-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-03
相关资源
最近更新 更多