簡體   English   中英

Asp.Net 核心 2.1 await 在第二次運行時不會將控制權交給調用者

[英]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 :-)

誰能告訴我我哪里出錯了?

讓我們明確幾件事:

  1. 線程不是放置在那里的神奇資源,為工作而工作
  2. 您擁有的線程數量越多,您需要管理它們的資源就越多
  3. 異步,雖然很有幫助也不是一件容易的事

好的,首先,您的應用程序以預定義數量的 w8ing 線程開始(通常是核心數* 2,如果我沒記錯的話,可以找到該死的 msdn 文章)。 如果您請求線程並且您在此限制下使用,您會立即獲得它們,否則,您將需要 w8 500 毫秒(找不到文章)

其次, 異步不是並行的

第三,在您的代碼中,無論何時使用 await,它都在等待! 因此,我建議您在OpenAsync上重構 await,與ContinueWith鏈接,並且只在您的代碼中使用一次 await,因為就目前而言,您的using正在阻止async正常工作......您將不得不管理如果您希望代碼異步運行,請自行連接和處置

編輯1:

有兩種類型的線程:IO 線程和工作線程。 在您的代碼中,您需要的是數據庫 w8 的 IO 線程……如果您需要更多上下文,可以從這里開始

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM