使用C#AsyncCTP中的ExecuteReaderAsync的任何缺点
本文关键字:任何 缺点 ExecuteReaderAsync C#AsyncCTP 中的 使用 | 更新日期: 2023-09-27 18:25:37
有些文章指出异步数据库调用在.NET.中是个坏主意
- 我的数据库调用应该是异步的吗
- 我的数据库调用应该是异步的吗第二部分
在C#异步CTP上,有一个名为ExecuteReaderAsync
的System.Data.SqlClient.SqlCommand
扩展。我对我现有的代码有一些操作如下:
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();
}
}
在我的代码中有几个类似的操作。因此,我正在考虑将这些转换为异步。
但另一方面,我没有看到这种方法有多大吸引力(也许我没有朝着正确的方向看,谁知道呢!)。
那么,在这里使用这种新的异步编程模型有什么缺点吗?
编辑:
假设我重构代码如下:
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关键字了解,它将后面的代码转换为continuation。此外,当它命中wait关键字时,无论操作状态如何,它都会立即返回给调用者。当它完成时,它会返回并激发延续代码。
这就是我的想法。
我不同意瑞卡的观点。异步DB命令不仅很好,而且在实现规模、吞吐量和延迟方面至关重要。他对线程池的提升时间的反对意见仅适用于流量较低的web服务器。
在高流量情况下(这是唯一重要的情况),线程池不必等待"注入"新线程。异步执行SQL命令不仅从web服务器请求/线程运行状况的角度来看很重要,而且从总请求寿命/延迟的角度来看也很重要:不相关的DB调用可以并行执行,而不是顺序执行。这一点通常会显著改善用户体验到的HTTP请求的延迟。换句话说,你的页面加载得更快。
不过,有一点建议:在连接字符串上启用Asynchronous Processing=true
之前,SQL命令并不是真正的异步命令。虽然未设置(默认情况下也未设置),但编辑:从.NET Framework<4.5开始。不再需要Asynchronous Processing
)如果对BeginExecuteReader
的"异步"调用只是一个骗局,则该调用将启动一个线程并阻止该线程。如果在连接字符串中启用了真正的异步处理,则调用是真正的异步,回调基于IO完成。
需要注意的是:第一个结果返回到客户端后,异步SQL命令就会完成,信息消息也会作为结果计数。
create procedure usp_DetailsTagsGetAllFromApprovedPropsWithCount
as
begin
print 'Hello';
select complex query;
end
您已经失去了异步的所有好处。print
创建一个结果,并将其发送回客户端,从而完成异步命令,客户端上的执行将恢复并使用"reader.Read()"继续。现在,将阻止该结果,直到复杂查询开始产生结果。你问‘谁把print
放在程序中?’,但print
可能被伪装成其他东西,可能看起来像INSERT
一样无辜,它执行而没有首先发布SET NOCOUNT ON
。
我注意到以下问题没有得到回答:
那么,在这里使用这种新的异步编程模型有什么缺点吗?
的缺点是非常小的(小cpu/小内存afaik),因为在wait语句之后运行的任何代码都有可能在单独的线程上运行,所以存在一个状态机来存储当前运行的线程的状态,以便在另一个线程上处理工作的继续。您可以在Dixin的博客-理解C#async/await(1)Compilation上阅读更多关于wait/async状态机的信息。