简体   繁体   English

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

[英]Asp.Net core 2.1 await doesn't yield control to caller on 2nd run

I am in the process of making all of my database operations asynchronous.我正在使所有数据库操作异步。 However, I don't seem to get the desired results of asynchrony.但是,我似乎没有得到所需的异步结果。

eg -例如——

I am inserting 100 rows to a table in a database in a loop.我在循环中将 100 行插入到数据库中的表中。 The function that does this is a async function.执行此操作的函数是异步函数。 It doesn't seem to yield control to its caller when its awaiting.在等待时,它似乎没有将控制权交给调用者。 The code is below -代码如下 -

[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;
}

When I call the API /api/logtest the very first time, I seem to get desired results with exec_time much less than await_time (0.2s vs 4s)当我第一次调用 API /api/logtest 时,我似乎得到了比 await_time 少得多的 exec_time 所需的结果(0.2s vs 4s)

However from 2nd run onwards I get await_time much less than exec_time (4s vs 0.2s) which is making me believe code ran synchronously.然而,从第二次运行开始,我得到的 await_time 远小于 exec_time(4s vs 0.2s),这让我相信代码是同步运行的。

Also the same code in a console app using .net framework 4.6.1, gives desired results continuously.使用 .net framework 4.6.1 的控制台应用程序中的相同代码也会持续提供所需的结果。 and no I did not restart the console app.不,我没有重新启动控制台应用程序。 Ran the BulkLogInsertAsync in a do while loop :-)在 do while 循环中运行 BulkLogInsertAsync :-)

Can anybody please tell me where I am going wrong ?谁能告诉我我哪里出错了?

Let's set a couple of things straight:让我们明确几件事:

  1. Threads are not magical resources that are just laying there, w8ing for work线程不是放置在那里的神奇资源,为工作而工作
  2. The higher number of threads you have, more resources you´ll need to manage them您拥有的线程数量越多,您需要管理它们的资源就越多
  3. Asynchrony, although very helpful is not an easy thing异步,虽然很有帮助也不是一件容易的事

Ok, first of all, your app starts with a predefined number of w8ing threads (usually number of cores*2, if i recall correctly, can find the damn msdn article).好的,首先,您的应用程序以预定义数量的 w8ing 线程开始(通常是核心数* 2,如果我没记错的话,可以找到该死的 msdn 文章)。 If you request threads and you´re using under this limit, you get them instantaneously, otherswise, you'll have to w8 500ms (cant find the article)如果您请求线程并且您在此限制下使用,您会立即获得它们,否则,您将需要 w8 500 毫秒(找不到文章)

Second, async is not parallel !其次, 异步不是并行的

Third, in your code, whenever you use await, it awaits!第三,在您的代码中,无论何时使用 await,它都在等待! so, i suggest you refactor await on OpenAsync , chaining with ContinueWith and only use the await once in your code, because, as it is right now, your using 's are preventing async from working properly... you will have to manage the connections and disposals on your own if you want the code to run asynchronously因此,我建议您在OpenAsync上重构 await,与ContinueWith链接,并且只在您的代码中使用一次 await,因为就目前而言,您的using正在阻止async正常工作......您将不得不管理如果您希望代码异步运行,请自行连接和处置

Edit1:编辑1:

There are 2 types of threads: IO Threads and Worker threads.有两种类型的线程:IO 线程和工作线程。 In your code, what you need is IO threads to w8 for the database... if you need more context on this, you can start here在您的代码中,您需要的是数据库 w8 的 IO 线程……如果您需要更多上下文,可以从这里开始

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM