C# 使用ADO.NET对Oracle DB的异步调用
我正在尝试使用.NETFramework4.5中提供的异步和等待功能执行多个数据库调用。这是我第一次实现此功能 如果每个查询耗时7秒,则通常需要35秒(5个查询*7秒)。在下面的实现中,我希望它能在7-9秒内获取并填充asp页面中的控件。然而,它仍然需要35秒,证明了我的同步行为 有人能帮助我在下面的异步实现中哪里出了问题吗 我很感激你的任何意见,从几天以来我一直在为这件事绞尽脑汁C# 使用ADO.NET对Oracle DB的异步调用,c#,asp.net,webforms,ado.net,async-await,C#,Asp.net,Webforms,Ado.net,Async Await,我正在尝试使用.NETFramework4.5中提供的异步和等待功能执行多个数据库调用。这是我第一次实现此功能 如果每个查询耗时7秒,则通常需要35秒(5个查询*7秒)。在下面的实现中,我希望它能在7-9秒内获取并填充asp页面中的控件。然而,它仍然需要35秒,证明了我的同步行为 有人能帮助我在下面的异步实现中哪里出了问题吗 我很感激你的任何意见,从几天以来我一直在为这件事绞尽脑汁 protected void Page_Load(object sender, System.EventA
protected void Page_Load(object sender, System.EventArgs e)
{
RegisterAsyncTask(new PageAsyncTask(FillControlsAsync));
}
public async Task FillControlsAsync()
{
Task[] tasks = new Task[]{
PopulateControlTask(query1, "controlID1"),
PopulateControlTask(query2, "controlID2"),
PopulateControlTask(query3, "controlID3"),
PopulateControlTask(query4, "controlID4"),
PopulateControlTask(query5, "controlID5")
});
await Task.WhenAll(tasks);
}
public async Task PopulateControlTask(string query, string control)
{
await Task.Run(() =>
{
DataSet ds;
OracleCommand cmd;
OracleDataAdapter da;
try
{
if (!Page.IsPostBack)
{
cmd = new OracleCommand(query, cn);
da = new OracleDataAdapter(cmd);
ds = new DataSet();
da.Fill(ds);
switch (control)
{
case "controlID1":
//some custom code for control 1
// like attaching the datasource to control.
break;
case "controlID2":
//some custom code for control 2
break;
case "controlID2":
//some custom code for control 3
break;
case "controlID3":
//some custom code for control 4
break;
case "controlID4":
//some custom code for control 5
break;
}
}
}
catch(Exception e)
{
//some error handling here
}
});
}
async
和await
用于异步代码。通常,如果您有一个可伸缩的数据库,您可以使db调用异步,从而扩展服务器。请注意,ASP.NET上的async
的主要好处是可伸缩性,而不是响应时间
然而,正如其他人所指出的,Oracle不支持异步代码
但这并不重要,因为您发布的代码一开始就不是异步的!这就是我所说的“伪异步”,因为它只是使用Task.Run
将同步工作推到后台线程,而不是使用自然异步API。(但如前所述,在本例中(即Oracle),您没有任何可使用的自然异步API)
因此,最终得到的是并行性,而不是异步性。特别是,代码将自己扩展到5个线程池线程上以完成其工作
现在,您需要做的第一件事是问问自己,您是否真的想要服务器上的并行性。您的请求将占用5个线程,而不是1(或0)。这会极大地影响web服务器的可伸缩性(以一种不好的方式)。此外,还要考虑后端的功能。如果是一台服务器,而这些查询都是在单个硬盘驱动器上访问单个数据库,那么将其中的5个并行化是否真的会产生任何好处,或者,由于磁盘争用,如果不是更糟的话,它是否真的会同样糟糕?(您应该能够快速启动一个控制台应用程序,测试您的数据库在空闲和负载下如何响应串行和并行请求)
我发现,绝大多数情况下,答案是“不,我不想让我的整个数据库服务器屈服于这一请求”——换句话说,避免服务器上的并行性
但是,如果您权衡了各种选择,认为是的,您的选择是ASP.NET上适合并行性的罕见案例之一,那么您应该问您在这里发布的问题:为什么这些选择是按顺序运行的,而不是同时运行的?(旁注:这里是顺序vs并发,而不是同步vs异步)
回答:我不知道
但我有一个猜测:如果数据库连接(cn
在您的代码片段中)是共享的,那么很可能db连接本身一次只限于一个查询。其他数据库连接系统也有类似的限制。我要做的第一件事是为每个查询提供自己的连接
也就是说,如果您想并行化web服务器。这是一个很大的“如果”
async
和wait
用于异步代码。通常,如果您有一个可伸缩的数据库,您可以使db调用异步,从而扩展服务器。请注意,ASP.NET上的async
的主要好处是可伸缩性,而不是响应时间
然而,正如其他人所指出的,Oracle不支持异步代码
但这并不重要,因为您发布的代码一开始就不是异步的!这就是我所说的“伪异步”,因为它只是使用Task.Run
将同步工作推到后台线程,而不是使用自然异步API。(但如前所述,在本例中(即Oracle),您没有任何可使用的自然异步API)
因此,最终得到的是并行性,而不是异步性。特别是,代码将自己扩展到5个线程池线程上以完成其工作
现在,您需要做的第一件事是问问自己,您是否真的想要服务器上的并行性。您的请求将占用5个线程,而不是1(或0)。这会极大地影响web服务器的可伸缩性(以一种不好的方式)。此外,还要考虑后端的功能。如果是一台服务器,而这些查询都是在单个硬盘驱动器上访问单个数据库,那么将其中的5个并行化是否真的会产生任何好处,或者,由于磁盘争用,如果不是更糟的话,它是否真的会同样糟糕?(您应该能够快速启动一个控制台应用程序,测试您的数据库在空闲和负载下如何响应串行和并行请求)
我发现,绝大多数情况下,答案是“不,我不想让我的整个数据库服务器屈服于这一请求”——换句话说,避免服务器上的并行性
但是,如果您权衡了各种选择,认为是的,您的选择是ASP.NET上适合并行性的罕见案例之一,那么您应该问您在这里发布的问题:为什么这些选择是按顺序运行的,而不是同时运行的?(旁注:这里是顺序vs并发,而不是同步vs异步)
回答:我不知道
但我有一个猜测:如果数据库连接(cn
在您的代码片段中)是共享的,那么很可能db连接本身一次只限于一个查询。其他数据库连接系统也有类似的限制。我要做的第一件事是为每个查询提供自己的连接
也就是说,如果您想并行化web服务器。哪一个是大的“如果”你真的有一个空的挡块吗?这是一种反模式