检查this GitHub issue;他们讨论了一些您可能感兴趣的事实。
你是对的。我们的 NetCore/Netstandard 支持还不包括 API 的同步实现。
请注意,此更改已在我们的路线图中作为向 .NetCore 过渡的同等项目之一,一旦可用,我们将更新更具体的时间表。
和
您能否向我们解释一下您对同步方法的需求是什么?总体而言,同步的资源效率远低于异步,因此我们不向客户推荐。如果您需要阻止异步调用,您可以随时使用 .GetAwaiter.GetResult()。
我们与提供此指导的 CLR 团队进行了一些对话:
如果您从库中公开异步端点,请避免公开仅包装异步实现的同步方法。这样做对消费者隐藏了实现的真实性质,应该由消费者决定如何使用实现。如果消费者选择阻塞等待异步实现完成,这取决于调用者,他们可以睁大眼睛这样做。
这对于“sync over async”的情况甚至比“async over sync”的情况更重要,因为对于“sync over async”,它可能会导致应用程序出现严重问题,例如挂起。
.NET Core 团队出于上述原因(资源消耗等)选择不支持真正的同步 api。即使我们实现了真正的同步,它最终也会在某种程度上成为异步同步。出于这个原因,我们认为添加虚假同步 api 将是一个障碍,而不是对我们的客户有帮助。如果您对此有任何反馈,请告诉我们。
pemari-msft 评论了May 11, 2017
和
让我解释一下原因。如果库使用不支持真正同步的库,则真正同步不是库的选项,就像我们和 .NET Core 的情况一样。 (无论如何,真正的同步对于进行网络调用的 API 来说有点用词不当,但这是一个不同的讨论。)所以我们有两个选择:创建一个同步异步包装器,或者让调用者来做。但正如我们所见,官方指导和普遍看法是应避免暴露包装。这是有充分理由的,它类似于避免包装同步调用的异步 API。避免使用此类 API 不仅可以保持 API 表面清洁,还可以避免混淆。客户会认为存在对同步或异步的真正支持,并在他们自己的公共接口中公开它,只是后来发现底层实现实际上并不支持它!所以我们得出的结论是,在这种情况下最好遵循流行的智慧。
你说得对,避免死锁是必不可少的,尤其是在同步异步场景中,所以让我稍微谈谈这是如何完成的。当线程调用异步方法然后阻塞等待结果时,就会出现死锁问题,而异步方法链正在等待线程释放以便它可以继续。解决方案是让异步方法在不受有限线程池约束的不同上下文中工作。这是在异步方法内部使用 ConfigureAwait 完成的,因此在库本身内避免了死锁。
如果您认为真正的同步很重要,那么您可以通过https://github.com/dotnet/corefx 提出这一点,以便在 .NET Core 中获得支持。
因此,您要么更改项目以避免 Azure,要么进行虚假同步调用。
然而,在 2018 年,观点发生了变化:
好吧,经过充分讨论,按照HttpWebRequest 的指导,我们决定提供同步方法作为异步同步。这是我们用户在未来版本的库中弃用同步 API 之前的时间缓冲区。
@copernicus365 ,为了让人们,特别是那些已经在使用该库的人更简单,我们的 Netstandard2.0 支持包括桌面和 Netcore 之间的功能奇偶性,将保留方法原样,在相同的命名空间中 /按服务拆分包的二进制文件(拆分包目前处于预览状态)。自然,我们需要响应 .NET 团队在我们的文档中提供的关于转换为异步的好处的指导,并尽可能清楚地表明它在幕后是异步同步的。
非常感谢所有花时间参与此主题并给我们反馈的人!
一个相关说明 - 对于已经在 .NET 桌面上使用同步方法的现有用户,这些方法也将转向异步同步。我们正在修改代码库以在任何地方使用 HttpClient(在桌面和 .NET Core 中),它不提供任何类型的真正同步。这是为了避免对所有内容进行单独的实现(一个使用 HttpWebRequest,一个使用 HttpClient),这导致了不同实现之间的许多错误和行为差异。
这些变化于 2018 年 5 月登陆 .NET Standard 2.0 目标。