【问题标题】:ConfigureAwait(false) with ADO.Net SQLConnection objectConfigureAwait(false) 与 ADO.Net SQLConnection 对象
【发布时间】:2017-03-23 12:55:41
【问题描述】:

我已经开始将ConfigureAwait(false) 与所有异步 sql 对象一起使用。

connection.OpenAsync().ConfigureAwait(false);
cmd.ExecuteNonQueryAsync().ConfigureAwait(false);

但我担心的是,这种方法会有什么影响吗?

由于这将在一个线程池上运行,该线程池是一个单独的线程,我不确定如果我们不在单个线程上运行它会产生什么后果。

我们的应用程序是 wcf 服务,它将并行处理 1000 条记录。

如果有人帮助识别可能出现问题的业务场景,那将是有帮助的。

谢谢

【问题讨论】:

  • 如果你不知道如何或为什么要使用它,你为什么要把它贴在所有东西上?
  • 在这里大声思考(我从未调查过),但我怀疑如果您使用ConfigureAwat(false)环境事务(又名TransactionScope)会非常失败 - 但是:我实际上并没有检查它们是否与aysnc without ConfigureAwait(false) 一起使用 :)
  • 我选择它是因为它会在多核环境中提升性能
  • @MarcGravell 有一个特殊的 constructor(从 .NET 4.5.1 开始),它允许您告诉 TransactionScope 它是否应该通过异步延续。但是如果你不使用这个构造函数(我认为大多数情况下) - 它不会流动。几天前我回答了一个问题,当时 OP 使用 TransactionScope 和 await 没有这个构造函数,这导致了令人惊讶的结果......
  • 我实际上最不关心我没有使用的 c# TransactionScope 对象。我在 Store Proc 中关注所有包含 SQL 事务的存储过程调用

标签: c# sql multithreading async-await configureawait


【解决方案1】:

作为一般规则,只要异步操作区域自包含且独立,使用ConfigureAwait(false) 应该没问题 - 实际上这样做对于减少开销和瓶颈很重要.库代码通常不需要了解调用上下文。但是,消费代码(例如winforms、MVC等)通常需要返回到适当的上下文,所以不应该使用@987654322 @。例如:

async Task SomeUXCodeAsync() {
    var data = await GetSomeDataAsync(); // note no ConfigureAwait(false)
    // not shown: use "data"
}
async Task<Foo> GetSomeDataAsync() {
    using(var conn = CreateConnection()) {
        await conn.OpenAsync().ConfigureAwait(false);
        ...
        int result = await cmd.ExecuteNonQueryAsync().ConfigureAwait(false);
        ...
        return ...
    }
}

上述场景非常典型和常见,比这更复杂 - cmets 中的 TransactionScope 示例涉及数据相关代码可能的示例> 例如,需要了解调用上下文。但除了细微差别:只要 消费 代码记得不要忽略调用上下文,您通常会回到正确的位置。抱歉,这有点含糊不清,但是:可悲的是,通常对于调用上下文来说是这样的。

【讨论】:

    猜你喜欢
    • 2015-04-30
    • 2017-06-22
    • 1970-01-01
    • 1970-01-01
    • 2017-11-08
    • 1970-01-01
    • 1970-01-01
    • 2012-06-07
    相关资源
    最近更新 更多