从 C# AsyncCTP 使用 ExecuteReaderAsync 的任何缺点 [英] Any disadvantage of using ExecuteReaderAsync from C# AsyncCTP

查看:14
本文介绍了从 C# AsyncCTP 使用 ExecuteReaderAsync 的任何缺点的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有些文章表明异步数据库调用在 .NET 中是个坏主意.

There are some articles which indicate that async database calls are bad idea in .NET.

在 C# Async CTP 上,有一个名为 ExecuteReaderAsyncSystem.Data.SqlClient.SqlCommand 扩展.我对现有代码进行了如下操作:

On C# Async CTP, there is a System.Data.SqlClient.SqlCommand extension called ExecuteReaderAsync. I have some operations as below on my existing code:

var connectionString = System.Configuration.ConfigurationManager.ConnectionStrings["hubConnectionString"].ConnectionString;

using (var conn = new SqlConnection(connectionString)) {
    using (var cmd = new SqlCommand()) {

        cmd.Connection = conn;
        cmd.CommandText = "sp$DetailsTagsGetAllFromApprovedPropsWithCount";
        cmd.CommandType = System.Data.CommandType.StoredProcedure;

        conn.Open();

        var reader = cmd.ExecuteReader();
        while (reader.Read()) {

            //do the reading

        }

        conn.Close();
    }
}

在我的代码中有几个这样的操作.所以,我正在考虑将它们转换为异步.

There are several operations like this on my code. So, I am having thoughts on converting those to async.

但另一方面,我认为这种方法没有太大吸引力(也许我看的方向不对,谁知道呢!).

But on the other hand, I am not seeing much attraction on this approach out there (maybe I am not looking at the right direction, who knows!).

那么,在这里使用这种新的异步编程模型有什么缺点吗?

So, is there any disadvantages of using this new async programming model here?

假设我重构代码如下:

public async Task<IEnumerable<Foo>> GetDataAsync() { 

    List<Foo> foos = new List<Foo>();

    var connectionString = System.Configuration.ConfigurationManager.ConnectionStrings["hubConnectionString"].ConnectionString;

    using (var conn = new SqlConnection(connectionString)) {
        using (var cmd = new SqlCommand()) {

            cmd.Connection = conn;
            cmd.CommandText = "sp$DetailsTagsGetAllFromApprovedPropsWithCount";
            cmd.CommandType = System.Data.CommandType.StoredProcedure;

            conn.Open();

            var reader = await cmd.ExecuteReaderAsync();
            while (reader.Read()) {

                //do the reading
                //create foos

            }

            conn.Close();
        }
    }

    return foos;

}

据我对 await 关键字的理解,它将后面的代码转换为延续.此外,当它遇到 await 关键字时,无论操作状态如何,它都会立即返回给调用者.当它完成时,它会返回并触发继续代码.

As far as I understand from the await keyword, it converts the code, which is after it, as continuation. Also, when it hits the await keyword, it immediately returns to its caller regardless of the operation status. When it finishes it comes back and fire the continuation code.

这就是我的想法.

推荐答案

我不同意 Ricka 的观点.异步数据库命令不仅很好,而且对于实现规模、吞吐量和延迟至关重要.他对线程池加速时间的反对意见仅适用于流量较低的 Web 服务器.

I disagree with Ricka on this. Async DB commands are not only good, they are critical in achieving scale, throughput and latency. His objection about the ramp up time of the thread pool applies only to a web server that experiences low traffic volumes.

在高流量情况下(这是唯一重要的情况),线程池不必等待注入"新线程.异步执行 SQL 命令不仅从 Web 服务器请求/线程健康的角度来看很重要,而且从总请求生命周期/延迟的角度来看也很重要:不相关的 DB 调用可以并行执行,而不是顺序执行.仅此一项通常会显着改善用户体验到的 HTTP 请求的延迟.换句话说,您的页面加载速度更快.

In a high traffic situation (which is the only one that matters), the thread pool won't have to wait for 'injecting' new threads. Doing the SQL Commands asynchronously is important not only from the point of view of web server requests/threads health, but also from the point of view of total request lifetime/latency: uncorrelated DB calls can be done in parallel, as opposed to sequentially. This alone results usually in dramatic improvements in the latency of the HTTP request as experienced by the user. In other words, your pages load faster.

尽管有一句忠告:SQL 命令并不是真正的异步,除非您启用 Asynchronous Processing=true 连接字符串.虽然未设置(默认情况下未设置,从 .NET Framework < 4.5 开始.不再需要异步处理)您对BeginExecuteReader 只不过是一个骗局,该调用将启动一个线程并阻塞那个线程.如果在连接字符串中启用了真正的异步处理,那么调用就是真正的异步,并且回调基于 IO 完成.

A word of advice though: SQL Command is not truly asynchronous until you enable Asynchronous Processing=true on the connection string. While this is not set (and by default is not, starting with .NET Framework < 4.5. Asynchronous Processing is no longer required) your 'asyncronous' calls to BeginExecuteReader are nothing but a sham, the call will launch a thread and block that thread. When true async processing is enabled in the connection string then the call is truly async and the callback is based on IO completion.

请注意:只要 第一个结果返回给客户端,异步 SQL 命令就会完成,信息消息也算作结果.

A word of caution: an async SQL command is completing as soon as the first result returns to the client, and info messages count as result.

create procedure usp_DetailsTagsGetAllFromApprovedPropsWithCount
as
begin
print 'Hello';
select complex query;
end

你已经失去了异步的所有好处.print 创建一个返回给客户端的结果,它完成异步命令,客户端上的执行恢复并继续reader.Read()".现在那个将阻塞,直到复杂的查询开始产生结果.你问'谁把 print 放在程序中?' 但是 print 可能被伪装成别的东西,也许看起来像 print 一样无辜代码>INSERT 执行没有首先发出SET NOCOUNT ON.

You've lost all benefits of async. The print creates a result that is sent back to the client, which completes the async command and execution on the client resumes and continues with the 'reader.Read()'. Now that will block until the complex query start producing results. You ask 'who puts print in the procedure?' but the print may be disguised in something else, perhaps something as innocent looking as an INSERT that executes without first issuing a SET NOCOUNT ON.

这篇关于从 C# AsyncCTP 使用 ExecuteReaderAsync 的任何缺点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆