从单独的程序集中调用异步扩展方法
Calling async extension methods from separate assembly
我在单独的程序集中遇到了有关异步扩展方法的奇怪行为。
我们有以下内容:
- 一个程序集处理
EventGridEvent
的发送。目标是 .NET Standard 2.0。此程序集引用 Microsoft.Azure.EventGrid
.
- 一个组件使用组件号。 1.目标是.NET Framework 4.7.
出于某种原因,从程序集 no. 制作同步方法。 2 至装配编号1 导致奇怪的行为。考虑我们在第 1 号装配体中的两个功能。 1:
public async Task PublishAsync(...)
{
await _eventGridClient.PublishEventsAsync(_eventGridTopicHostName, ...);
}
public void Publish(...)
{
_eventGridClient.PublishEventsAsync(_eventGridTopicHostName, ...).Wait();
}
如果我们从第一个程序集调用第一个方法。 2 与 PublishAsync().Wait()
,它永远不会 return。但是,Publish()
会。但是,如果 Publish()
调用 PublishAsync().Wait()
,该方法也会挂起。
值得一提的是EventGridClient
包含LongRunningOperationRetryTimeout
,默认设置为30,被忽略。它永远不会 returns.
有人知道是什么原因导致了这种行为吗?解决方法是复制代码,但我们希望避免这种情况。
提前致谢。
您永远不应该通过在返回的 Task
上调用 Wait()
或 .Result
来阻塞异步代码。 @Stephen Cleary 解释了为什么 on his blog.
调用_eventGridClient.PublishEventsAsync
时,捕获SynchronizationContext
。当任务完成时,它会等待上下文变得可用,但它永远不会,因为您通过调用 .Wait()
阻止了它。这会导致死锁。
您可以通过调用 ConfigureAwait(false)
:
避免捕获上下文来摆脱麻烦
public async Task PublishAsync(...)
{
await _eventGridClient.PublishEventsAsync(_eventGridTopicHostName, ...)
.ConfigureAwait(false);
}
但最好的解决办法还是完全不阻塞。如链接博客 post.
中所述,异步代码应为 "async all the way"
问题是调用方法是 运行 在 UI 线程上。它是通过像这样包装调用来解决的:Task.Run(() => ...).Wait()
我在单独的程序集中遇到了有关异步扩展方法的奇怪行为。
我们有以下内容:
- 一个程序集处理
EventGridEvent
的发送。目标是 .NET Standard 2.0。此程序集引用Microsoft.Azure.EventGrid
. - 一个组件使用组件号。 1.目标是.NET Framework 4.7.
出于某种原因,从程序集 no. 制作同步方法。 2 至装配编号1 导致奇怪的行为。考虑我们在第 1 号装配体中的两个功能。 1:
public async Task PublishAsync(...)
{
await _eventGridClient.PublishEventsAsync(_eventGridTopicHostName, ...);
}
public void Publish(...)
{
_eventGridClient.PublishEventsAsync(_eventGridTopicHostName, ...).Wait();
}
如果我们从第一个程序集调用第一个方法。 2 与 PublishAsync().Wait()
,它永远不会 return。但是,Publish()
会。但是,如果 Publish()
调用 PublishAsync().Wait()
,该方法也会挂起。
值得一提的是EventGridClient
包含LongRunningOperationRetryTimeout
,默认设置为30,被忽略。它永远不会 returns.
有人知道是什么原因导致了这种行为吗?解决方法是复制代码,但我们希望避免这种情况。
提前致谢。
您永远不应该通过在返回的 Task
上调用 Wait()
或 .Result
来阻塞异步代码。 @Stephen Cleary 解释了为什么 on his blog.
调用_eventGridClient.PublishEventsAsync
时,捕获SynchronizationContext
。当任务完成时,它会等待上下文变得可用,但它永远不会,因为您通过调用 .Wait()
阻止了它。这会导致死锁。
您可以通过调用 ConfigureAwait(false)
:
public async Task PublishAsync(...)
{
await _eventGridClient.PublishEventsAsync(_eventGridTopicHostName, ...)
.ConfigureAwait(false);
}
但最好的解决办法还是完全不阻塞。如链接博客 post.
中所述,异步代码应为 "async all the way"问题是调用方法是 运行 在 UI 线程上。它是通过像这样包装调用来解决的:Task.Run(() => ...).Wait()