[英]Asp.Net core 2.1 await doesn't yield control to caller on 2nd run
我正在使所有数据库操作异步。 但是,我似乎没有得到所需的异步结果。
例如——
我在循环中将 100 行插入到数据库中的表中。 执行此操作的函数是异步函数。 在等待时,它似乎没有将控制权交给调用者。 代码如下 -
[HttpGet]
[Route("/api/logtest")]
public async Task<JObject> logTestAsync()
{
JObject retval = new JObject();
DateTime dt1 = DateTime.Now;
Task t = BulkLogInsertAsync();
DateTime dt2 = DateTime.Now;
retval["Exec_Time"] = dt2.Subtract(dt1).TotalMilliseconds;
await t;
DateTime dt3 = DateTime.Now;
retval["Await_Time"] = dt3.Subtract(dt2).TotalMilliseconds;
return retval;
}
private async Task BulkLogInsertAsync()
{
List<Task<int>> allTasks = new List<Task<int>>();
for (int i = 0; i<100;i++)
{
allTasks.Add(LogInsertAsync("insert into logs values (getdate() , 'custom' , 'sample message. ', 'Log.bills', 'callsite1', '', '', '')"));
//allTasks.Add(LogInsertAsync("WAITFOR DELAY '00:00:02';"));
}
await Task.WhenAll(allTasks.ToArray()).ConfigureAwait(false);
}
private async Task<int> LogInsertAsync(string cmd)
{
int res = 0;
using (SqlConnection hookup = new SqlConnection(@"[mycnstr]"))
{
Task connectionOpeningTask = hookup.OpenAsync();
using (SqlCommand sqlcmd = new SqlCommand(cmd, hookup))
{
await connectionOpeningTask.ConfigureAwait(false);
res = await sqlcmd.ExecuteNonQueryAsync().ConfigureAwait(false);
}
hookup.Close();
}
return res;
}
当我第一次调用 API /api/logtest 时,我似乎得到了比 await_time 少得多的 exec_time 所需的结果(0.2s vs 4s)
然而,从第二次运行开始,我得到的 await_time 远小于 exec_time(4s vs 0.2s),这让我相信代码是同步运行的。
使用 .net framework 4.6.1 的控制台应用程序中的相同代码也会持续提供所需的结果。 不,我没有重新启动控制台应用程序。 在 do while 循环中运行 BulkLogInsertAsync :-)
谁能告诉我我哪里出错了?
让我们明确几件事:
好的,首先,您的应用程序以预定义数量的 w8ing 线程开始(通常是核心数* 2,如果我没记错的话,可以找到该死的 msdn 文章)。 如果您请求线程并且您在此限制下使用,您会立即获得它们,否则,您将需要 w8 500 毫秒(找不到文章)
其次, 异步不是并行的!
第三,在您的代码中,无论何时使用 await,它都在等待! 因此,我建议您在OpenAsync
上重构 await,与ContinueWith
链接,并且只在您的代码中使用一次 await,因为就目前而言,您的using
正在阻止async
正常工作......您将不得不管理如果您希望代码异步运行,请自行连接和处置
编辑1:
有两种类型的线程:IO 线程和工作线程。 在您的代码中,您需要的是数据库 w8 的 IO 线程……如果您需要更多上下文,可以从这里开始
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.