繁体   English   中英

从单独的程序集中调用异步扩展方法

[英]Calling async extension methods from separate assembly

我在单独的程序集中遇到了关于异步扩展方法的奇怪行为。

我们有以下几点:

  1. 一种处理EventGridEvent发送的程序EventGridEvent 目标是 .NET Standard 2.0。 此程序集引用Microsoft.Azure.EventGrid
  2. 使用装配编号的一个装配。 1. 目标是 .NET Framework 4.7。

出于某种原因,从程序集没有制作同步方法。 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM