Почему Task.Delay() допускает бесконечную задержку?
После того, как мое приложение застыло, я отследил причину потока, ожидающего выполнения задачи, созданной Task.Delay()
(или TaskEx.Delay()
в .NET 4.0), для которой он предоставил вычисленный TimeSpan
, который из-за ошибки, иногда вычислялся до TimeSpan
с TotalMilliseconds
меньше или равным -1
и больше, чем -2
(т.е. где-то между -10000-19999 тиками включительно).
Похоже, что когда вы передаете отрицательный TimeSpan
, который равен -2
миллисекундам или ниже, метод корректно выбрасывает ArgumentOutOfRangeException
, но когда вы предоставляете отрицательный TimeSpan из диапазона, описанного выше, он возвращает Task
, который никогда не завершается (установив базовый System.Threading.Timer
в dueTime
of -1, который обозначает бесконечность). Это означает, что любые продолжения, заданные для этой задачи, никогда не будут выполняться, и любой бедный поток, который происходит с .Wait()
на этом Task
, навсегда будет заблокирован.
Какое возможное использование может иметь Task
, которое никогда не завершено? Кто-нибудь ожидает такую возвращаемую стоимость? Если никакое отрицательное значение не передавалось на .Delay()
, включая значения в этом специальном диапазоне, введите ArgumentOutOfRangeException
?
Ответы
Ответ 1
Timeout.Infinite или -1 полезен, когда вы хотите бесконечно ждать долговременной задачи, для завершения которой потребуется неопределенное количество времени, но в конечном итоге завершена.
В API Win32 также используется константа INFINITE = -1 для бесконечных тайм-аутов.
Обычно вы не хотели бы использовать его в потоке пользовательского интерфейса, так как это могло бы заморозить пользовательский интерфейс (который, кажется, является вашей проблемой). Но в рабочем потоке есть допустимые варианты использования - например, сервер, который блокирует ожидание соединения с клиентом.
Ответ 2
В насмешливых сценариях, где я хочу убедиться, что мой код в блоке Task.WhenAny() обрабатывает одну из ожидаемых должным образом задач, я могу высмеять другие задачи и использовать бесконечную задержку, чтобы гарантировать, что задача. WhenAny обрабатывает задачу, которую я не высмеивал как бесконечную задержку.