简体   繁体   中英

Asp .net mvc: async controller method blocks incoming requests

In asp .net MVC project I'm trying to call controller's Get method with some long lasting operation asynchronously. The problem is that after first call other incoming requests are waiting when this operation will be finished. And after that they are handled one by one in order they were requested.

Tested on code below. So if for example I make requests to SomeGetMethod multiple times, for the incoming request this method will be executed only when SomeGetMethod finished for previous call.

public class SomeController : Controller
{

    public ActionResult Index()
    {
        return View();
    }

    public async Task<ActionResult> SomeGetMethod(int id)
    {
        await TestAsync();
        return Content("1");
    }


    public async Task<int> TestAsync()
    {

        await Task.Run(() => Thread.Sleep(20000));

        return 1;
    }
}

What might be the reason of that? Thanks in advance!

Task.Run could be executed on the same thread as your controller, so you should change Thread.Sleep with Task.Delay .

No that not the case. Its been pretending like this because both of the API's have same level of thread.sleep so its obvious that it will perform FIFO behavior ie API hits first will response first

To verify this kindly set Thread.Sleep(1) for the second API during debugging and you will find out that second API will response before the response of first API.

You can also verify by placing a debugger and you will find out that second API will hit server as soon as you send request.

You are experiencing Threadpool starvation . You start off with relatively few threads in your pool that can service requests. What you are doing is blocking a threadpool thread for 20 seconds, which means it is doing nothing for that period. When you hit that endpoint over and over, you will run into a situation where all your threads that can service requests are tied up, doing nothing but waiting.

To fix this, don't offload to a threadpool thread ie don't do Task.Run() and change to await Task.Delay(20000) for optimal throughput.

You should do a more correct test, so only one of the methods is waiting.

public class SomeController : Controller
{

    public ActionResult Index()
    {
        return View();
    }

    public ActionResult NoWait()
    {
        return Content("1");
    }


    public async Task<int> SleepWait()
    {

        await Task.Run(() => Thread.Sleep(20000));

        return 2;
    }
}

Then call SleepWait() and right after NoWait() , what is the output then?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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