[英]Calling async extension methods from separate assembly
我在单独的程序集中遇到了关于异步扩展方法的奇怪行为。
我们有以下几点:
EventGridEvent
发送的程序EventGridEvent
。 目标是 .NET Standard 2.0。 此程序集引用Microsoft.Azure.EventGrid
。出于某种原因,从程序集没有制作同步方法。 2 到装配编号。 1 导致奇怪的行为。 考虑我们在程序集中的两个函数。 1:
public async Task PublishAsync(...)
{
await _eventGridClient.PublishEventsAsync(_eventGridTopicHostName, ...);
}
public void Publish(...)
{
_eventGridClient.PublishEventsAsync(_eventGridTopicHostName, ...).Wait();
}
如果我们从程序集编号调用第一个方法。 2 使用PublishAsync().Wait()
,它将永远不会返回。 然而, Publish()
会。 但是,如果Publish()
调用PublishAsync().Wait()
,该方法也会挂起。
值得一提的是, EventGridClient
包含LongRunningOperationRetryTimeout
,默认设置为 30,被忽略。 它永远不会回来。
任何人都知道是什么导致了这种行为? 一种解决方法是复制代码,但我们希望避免这种情况。
提前致谢。
您永远不应该通过在返回的Task
上调用Wait()
或.Result
来阻塞异步代码。 @Stephen Cleary 在他的博客上解释了原因。
调用_eventGridClient.PublishEventsAsync
,会捕获SynchronizationContext
。 当任务完成时,它会等待上下文变为可用,但它永远不会,因为您通过调用.Wait()
阻止了它。 这会导致僵局。
您可以通过调用ConfigureAwait(false)
避免捕获上下文来解决问题:
public async Task PublishAsync(...)
{
await _eventGridClient.PublishEventsAsync(_eventGridTopicHostName, ...)
.ConfigureAwait(false);
}
但最好的解决方案仍然是根本不阻止。 如链接的博客文章中所述,异步代码应该是“一路异步”。
问题是调用方法在 UI 线程上运行。 它是通过像这样包装调用来解决的: Task.Run(() => ...).Wait()
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.