Asp.Net core 2.1 wait 在第二次运行时不会将控制权交给调用者

问题描述 投票:0回答:1

我正在使所有数据库操作异步。但是,我似乎没有得到异步的预期结果。

例如-

我正在循环中向数据库中的表中插入 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 时,我似乎得到了所需的结果,其中 exec_time 比 wait_time 少得多(0.2 秒 vs 4 秒)

但是从第二次运行开始,我得到的await_time比exec_time少得多(4s vs 0.2s),这让我相信代码是同步运行的。

使用 .net Framework 4.6.1 的控制台应用程序中的相同代码也可以连续给出所需的结果。不,我没有重新启动控制台应用程序。在 do while 循环中运行 BulkLogInsertAsync :-)

有人可以告诉我哪里出错了吗?

c# asynchronous async-await asp.net-core-2.1
1个回答
1
投票

让我们澄清一些事情:

  1. 线程并不是只是躺在那里等待工作的神奇资源
  2. 您拥有的线程数量越多,管理它们所需的资源就越多
  3. 异步,虽然很有帮助,但并不是一件容易的事情

好吧,首先,你的应用程序以预定义数量的等待线程启动(通常是核心数*2,如果我没记错的话,我找不到那篇该死的 MSDN 文章)。如果你请求线程并且你在这个限制下使用,你会立即获得它们,否则,你将不得不等待 500 毫秒(找不到文章)

第二,异步不是并行

第三,在你的代码中,只要你使用await,它就会等待!所以,我建议你重构

OpenAsync
上的等待,与
ContinueWith
链接,并且只在代码中使用一次等待,因为,就像现在一样,你的
using
正在阻止
async
正常工作。 ..如果您希望代码异步运行,您将必须自己管理连接和处置

编辑1:

线程有两种类型:IO线程和工作线程。在你的代码中,你需要的是数据库的 IO 线程到 w8...如果你需要更多上下文,你可以从这里开始

© www.soinside.com 2019 - 2024. All rights reserved.