首页 > C# > C#对所有服务器端代码调用 ConfigureAwait 的最佳实践

C#对所有服务器端代码调用 ConfigureAwait 的最佳实践

上一篇 下一篇

当你有服务器端代码(即一些)并且你的函数是异步的 – 所以它们返回 – 是否被认为是最佳实践,任何时候你等待你调用的函数?ApiControllerTask<SomeObject>ConfigureAwait(false)

我读过它的性能更高,因为它不必将线程上下文切换回原始线程上下文。但是,对于 Web API ASP.NET,如果您的请求在一个线程上传入,并且您等待某个函数和调用,当您返回函数的最终结果时,这可能会将您置于不同的线程上。ConfigureAwait(false)ApiController

我在下面输入了一个我正在谈论的示例:

public class CustomerController : ApiController
{
    public async Task<Customer> Get(int id)
    {
        // you are on a particular thread here
        var customer = await GetCustomerAsync(id).ConfigureAwait(false);
        
        // now you are on a different thread!  will that cause problems?
        return customer;
    }
}

分割线

网友回答:

更新:ASP.NET 核心没有 .如果您使用的是 ASP.NET Core,则是否使用并不重要。SynchronizationContextConfigureAwait(false)

对于 ASP.NET“完整”或“经典”或其他什么,此答案的其余部分仍然适用。

原始帖子(非核心 ASP.NET):

ASP.NET 团队的这段视频提供了有关在 ASP.NET 上使用的最佳信息。async

我读过它的性能更高,因为它不必将线程上下文切换回原始线程上下文。

对于 UI 应用程序也是如此,其中只有一个 UI 线程必须“同步”回去。

在 ASP.NET,情况要复杂一些。当方法恢复执行时,它会从 ASP.NET 线程池中获取线程。如果使用 禁用上下文捕获,则线程只会继续直接执行该方法。如果不禁用上下文捕获,则线程将重新进入请求上下文,然后继续执行该方法。asyncConfigureAwait(false)

所以不会为您节省 ASP.NET 线程跳转;它确实可以节省您重新输入请求上下文的时间,但这通常非常快。 如果您尝试对请求进行少量并行处理,可能会很有用,但实际上 TPL 更适合大多数这些场景。ConfigureAwait(false)ConfigureAwait(false)

但是,对于 ASP.NET Web Api,如果您的请求在一个线程上传入,并且您等待某个函数并调用 ConfigureAwait(false),这可能会在返回 ApiController 函数的最终结果时将您置于不同的线程上。

实际上,只要做一个就可以做到这一点。一旦您的方法命中 ,该方法就会被阻塞,但线程会返回到线程池。当方法准备好继续时,将从线程池中抢取任何线程并用于恢复该方法。awaitasyncawait

ASP.NET 的唯一区别是该线程在恢复方法时是否进入请求上下文。ConfigureAwait

我的 MSDN 文章和我的介绍博客文章中有更多背景信息。SynchronizationContextasync

分割线

网友回答:

简要回答您的问题:不。您不应该像那样在应用程序级别调用。ConfigureAwait(false)

TL;DR 版本的长答案:如果您正在编写一个不了解使用者并且不需要同步上下文的库(我认为您不应该在库中使用),则应始终使用 .否则,库的使用者可能会因以阻塞方式使用异步方法而面临死锁。这取决于情况。ConfigureAwait(false)

以下是关于方法重要性的更详细的解释(引用我的博客文章):ConfigureAwait

当您等待带有 await 关键字的方法时,编译器
会代表您生成一堆代码。此操作
的目的之一是处理与 UI(或主)线程的同步。此功能的关键
组件是
获取当前线程的同步上下文的。
根据您所在
的环境进行填充。任务的方法查找
。如果当前同步上下文不为
null,则传递给该等待者的继续将
回发到该同步上下文。
SynchronizationContext.CurrentSynchronizationContext.CurrentGetAwaiterSynchronizationContext.Current

当以阻塞方式使用使用新的异步语言
功能的方法时,如果您有可用的 SynchronizationContext,则
最终会出现死锁。当您以阻塞方式使用
此类方法(等待带有 Wait
方法的任务或直接从任务的
Result 属性获取结果)时,您将同时阻塞主线程。当最终任务在线程池中的该方法内完成时
,它将
调用延续以回发到主线程
,因为可用且已捕获。但是
这里有一个问题:UI 线程被阻止,你有一个
死锁!
SynchronizationContext.Current

另外,这里有两篇很棒的文章,完全适合您的问题:

  • 搬起石头砸自己的脚的完美秘诀 – 使用 C# 5.0 异步语言功能以死锁告终
  • HTTP API 的异步 .NET 客户端库以及对 async/await 不良影响的感知

最后,Lucian Wischik有一个关于这个主题的精彩短视频:异步库方法应考虑使用Task.ConfigureAwait(false)。

分割线

网友回答:

我发现使用 ConfigureAwait(false) 的最大缺点是线程区域性恢复为系统默认值。如果您已配置区域性,例如…

<system.web>
    <globalization culture="en-AU" uiCulture="en-AU" />    
    ...

并且您托管在区域设置为 en-US 的服务器上,然后您会发现在 ConfigureAwait(false) 称为 CultureInfo.CurrentCulture 之前返回 en-AU,之后您将获得 en-US。

// CultureInfo.CurrentCulture ~ {en-AU}
await xxxx.ConfigureAwait(false);
// CultureInfo.CurrentCulture ~ {en-US}

如果你的应用程序正在做任何需要特定于区域性的数据格式的事情,那么在使用 ConfigureAwait(false) 时需要注意这一点。

模板简介:该模板名称为【C#对所有服务器端代码调用 ConfigureAwait 的最佳实践】,大小是暂无信息,文档格式为.编程语言,推荐使用Sublime/Dreamweaver/HBuilder打开,作品中的图片,文字等数据均可修改,图片请在作品中选中图片替换即可,文字修改直接点击文字修改即可,您也可以新增或修改作品中的内容,该模板来自用户分享,如有侵权行为请联系网站客服处理。欢迎来懒人模板【C#】栏目查找您需要的精美模板。

相关搜索
  • 下载密码 lanrenmb
  • 下载次数 309次
  • 使用软件 Sublime/Dreamweaver/HBuilder
  • 文件格式 编程语言
  • 文件大小 暂无信息
  • 上传时间 04-21
  • 作者 网友投稿
  • 肖像权 人物画像及字体仅供参考
栏目分类 更多 >
热门推荐 更多 >
单页式简历模板 自适应 微信图片 响应式 微信公众平台 微信文章 微信模板 企业网站 html5 微信素材
您可能会喜欢的其他模板