繁体   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