[英]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.