Что происходит в длительном asyn c методе до задержки? - PullRequest
3 голосов
/ 26 марта 2020

У меня есть метод, который отправляет запрос на мой сервер каждую секунду.

public async Task StartRequestProcess(CancellationToken stoppingToken)
{
    while (!stoppingToken.IsCanecllationRequested)
    {
       var result = await GetDataFromServerAsync();
       await Task.Delay(1000, stoppingToken);
    }
}

Но мой метод GetDataFromServerAsync() иногда занимает 10 или 15 секунд.

Что делает в это время ( 10 или 15 секунд)?

Будет ли процесс ждать завершения длинных запросов? Или новые запросы будут отправляться каждую секунду без ожидания?

Ответы [ 3 ]

8 голосов
/ 26 марта 2020

У меня есть метод, который отправляет запрос на мой сервер каждую секунду.

Нет, у вас нет. Пожалуйста, не открывайте вопросы с ложными утверждениями; это затрудняет их ответ!

Ваш рабочий процесс:

  • Запрос данных
  • Ожидание получения данных - вот что асинхронно ждет означает. await означает асинхронное ожидание .
  • Как только данные поступят, снова сделайте паузу на секунду, опять же, асинхронно
  • Повтор.

Это НЕ рабочий процесс "отправлять запрос каждую секунду". То есть рабочий процесс «отправить запрос через одну секунду после того, как последний запрос был выполнен».

Что делает в это время (10 или 15 секунд)?

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

Будет ли рабочий процесс ожидать завершения длинного запроса?

Да. Он будет ждать асинхронно . Опять же, это то, что означает await. Это означает асинхронное ожидание .

Будут ли новые запросы отправляться каждую секунду без ожидания?

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

1 голос
/ 26 марта 2020

Вся идея TAP (шаблон задачи Asyn c) состоит в том, что один поток может обслуживать множество вещей «одновременно», потому что он может go вернуться к тому, что делал раньше, в любое время, когда await в процессе. Вот почему асин c маркировка на методах имеет тенденцию быть на каждом методе вплоть до иерархии, начиная с первой точки, которую код, который вы пишете (ваш метод Get-метод, например), через каждый метод, который вы вызываете, вплоть до где нужно ждать что-то вроде БД или сетевого ввода-вывода.

Встреча await немного похожа на создание необработанного исключения - поток управления идет обратно по всему стеку методов, который является вашим кодом, и, вернувшись, возвращается к тому, что происходило до этого. вне вашего кода. Разница между сгенерированным исключением и конечным автоматом ожидания состоит в том, что, когда ожидаемая задача выполнена, поток, завершивший выполнение других задач, вернется туда, где находится ожидание, и продолжит оттуда

Что раньше это было очень контекстно - в вашем случае это, вероятно, «ожидание TCP-клиента для соединения и отправки некоторых данных»

Теперь, в вашем коде поток возвращается к тому, что он делал раньше - вы Допустим, это занимает 15 секунд, поэтому поток будет занят другими вещами в течение 15 секунд, затем он вернется и будет ждать завершения задачи 1000 мс, затем он округлит oop и выдаст другой запрос. На практике это означает, что каждые 16 секунд ваш код отправляет запрос; не просьба каждую секунду, на которую вы надеялись. Используйте таймер

0 голосов
/ 26 марта 2020

Когда вы вызываете await GetDataFromServerAsync(), выполнение вашего метода возобновится после завершения асинхронной операции, например, через 10-15 секунд. Только тогда вы будете асинхронно ждать еще одну секунду.

...