从 C# AsyncCTP 使用 ExecuteReaderAsync 的任何缺点
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9432647/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Any disadvantage of using ExecuteReaderAsync from C# AsyncCTP
提问by tugberk
There are some articles which indicate that async database calls are bad idea in .NET.
有一些文章表明异步数据库调用在 .NET 中是个坏主意。
On C# Async CTP, there is a System.Data.SqlClient.SqlCommandextension called ExecuteReaderAsync. I have some operations as below on my existing code:
在 C# Async CTP 上,有一个System.Data.SqlClient.SqlCommand扩展名为ExecuteReaderAsync. 我对现有代码进行了如下操作:
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?
那么,在这里使用这种新的异步编程模型有什么缺点吗?
Edit:
编辑:
Assuming I refactor the code as below:
假设我重构代码如下:
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;
}
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.
据我从 await 关键字中了解到,它将其后的代码转换为延续。此外,当它遇到 await 关键字时,无论操作状态如何,它都会立即返回到其调用者。当它完成时,它返回并触发继续代码。
This is what I have in mind.
这就是我的想法。
采纳答案by Remus Rusanu
I disagree with Ricka on this. Async DB commands are not only good, they are critical in achieving scale, throughput andlatency. His objection about the ramp up time of the thread pool applies only to a web server that experiences low traffic volumes.
在这点上我不同意 Ricka。异步数据库命令不仅很好,而且对于实现规模、吞吐量和延迟至关重要。他对线程池加速时间的反对意见仅适用于流量较低的 Web 服务器。
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 命令不仅从 Web 服务器请求/线程健康的角度来看很重要,而且从总请求生命周期/延迟的角度来看也很重要:不相关的 DB 调用可以并行执行,而不是顺序执行。仅此一项通常会显着改善用户体验到的 HTTP 请求的延迟。换句话说,您的页面加载速度更快。
A word of advice though: SQL Command is not truly asynchronous until you enable Asynchronous Processing=trueon the connection string. While this is not set (and by default is not, Edit: starting with .NET Framework < 4.5. Asynchronous Processingis no longer required) your 'asyncronous' calls to BeginExecuteReaderare nothing but a sham, the call will launch a thread and block thatthread. When true async processing is enabled in the connection stringthen the call is truly async and the callback is based on IO completion.
不过有一句忠告:在您启用Asynchronous Processing=true连接字符串之前,SQL 命令并不是真正的异步。虽然这没有设置(默认情况下没有,编辑:从 .NET Framework < 4.5 开始 Asynchronous Processing不再需要)你的“异步”调用BeginExecuteReader只是一个假动作,调用将启动一个线程并阻止该线程。当在连接字符串中启用真正的异步处理时,调用是真正的异步并且回调基于 IO 完成。
A word of caution: an async SQL command is completing as soon as the firstresult returns to the client, and info messages count as result.
提醒一句:当第一个结果返回给客户端时,异步 SQL 命令就会完成,并且信息消息计为结果。
create procedure usp_DetailsTagsGetAllFromApprovedPropsWithCount
as
begin
print 'Hello';
select complex query;
end
You've lost all benefits of async. The printcreates 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 thatwill block until the complex query start producing results. You ask 'who puts printin the procedure?'but the printmay be disguised in something else, perhaps something as innocent looking as an INSERTthat executes withoutfirst issuing a SET NOCOUNT ON.
你已经失去了异步的所有好处。在print建立了一个发送回客户端,这完成在客户端恢复异步命令和执行,并与“reader.Read()”继续的结果。现在这将阻塞,直到复杂查询开始产生结果。你问'谁安排print的程序?但是print可能会伪装成其他东西,也许看起来像INSERT在不首先发出SET NOCOUNT ON.
回答by Erik Philips
I notice that the following question wasn't answered:
我注意到以下问题没有得到回答:
So, is there any disadvantages of using this new async programming model here?
那么,在这里使用这种新的异步编程模型有什么缺点吗?
The disadvantagewhich is very minimal(minor cpu/minor memory afaik), is that because there is the possibility of any code running after an await statement mayrun on a separate thread, a state-machine exists to store the state of the currently running thread so that the continuation of work can be handled on another thread. You can read more about the await/async statemachine on Dixin's Blog - Understanding C# async / await (1) Compilation.
的缺点是非常小的(次要CPU /次要存储器AFAIK),是因为有一个AWAIT语句之后运行的任何代码的可能性可以在单独的线程上运行,一个状态机的存在是为了存储当前正在运行的状态线程,以便可以在另一个线程上处理继续工作。您可以在 Dixin 的博客上阅读有关await/async 状态机的更多信息- 理解 C# async/await (1) 编译。

