Почему 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 обрабатывает задачу, которую я не высмеивал как бесконечную задержку.