Asp. net mvc: asyn c метод контроллера блокирует входящие запросы - PullRequest
0 голосов
/ 02 мая 2020

В asp. net MVC проекте Я пытаюсь вызвать метод Get контроллера с какой-то длительной операцией асинхронно. Проблема в том, что после первого звонка другие входящие запросы ждут, когда эта операция будет завершена. И после этого они обрабатываются один за другим в порядке их запроса.

Проверено на приведенном ниже коде. Так, если, например, я делаю запросы к SomeGetMethod несколько раз, для входящего запроса этот метод будет выполняться только после завершения SomeGetMethod для предыдущего вызова.

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

В чем может быть причина этого? Заранее спасибо!

Ответы [ 4 ]

1 голос
/ 02 мая 2020

Task.Run может выполняться в том же потоке, что и ваш контроллер, поэтому вы должны изменить Thread.Sleep на Task.Delay.

0 голосов
/ 03 мая 2020

Вы испытываете Поток резьбы . Вы начинаете с относительно небольшого количества потоков в вашем пуле, которые могут обслуживать запросы. Вы блокируете поток пула потоков на 20 секунд, что означает, что он ничего не делает в течение этого периода. Когда вы достигаете этой конечной точки снова и снова, вы попадаете в ситуацию, когда все ваши потоки, которые могут обслуживать запросы, связаны, ничего не делая, кроме ожидания.

Чтобы исправить это, не выгружайте в поток пула потоков то есть не делайте Task.Run() и измените на await Task.Delay(20000) для оптимальной пропускной способности.

0 голосов
/ 02 мая 2020

Нет, это не так. Он притворяется таким, потому что оба API имеют одинаковый уровень thread.sleep, поэтому очевидно, что он будет выполнять поведение FIFO, то есть попадание API первым ответит первым

Чтобы убедиться, что это любезно установлено Thread.Sleep(1) для второго API во время отладки, и вы обнаружите, что второй API будет отвечать до ответа первого API.

Вы также можете проверить это, установив отладчик, и вы обнаружите, что второй API попадет на сервер, как только вы отправите запрос.

0 голосов
/ 02 мая 2020

Вы должны выполнить более правильный тест, поэтому только один из методов ожидает.

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

Затем вызовите SleepWait() и сразу после NoWait(), что тогда выводится?

...