Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does Task.Delay() allow an infinite delay?

After my application froze I tracked down the cause to a thread waiting on a task created by Task.Delay() (or TaskEx.Delay() in .NET 4.0) for which it provided a computed TimeSpan that, due to a bug, was on occasion computed to a TimeSpan with a TotalMilliseconds of less than or equal to -1 and greater than -2 (i.e. anywhere between -10000 to -19999 ticks, inclusive).

It appears that when you pass a negative TimeSpan that is -2 milliseconds or lower, the method correctly throws an ArgumentOutOfRangeException, but when you provide a negative TimeSpan from the range described above, it returns a Task that never completes (by setting the underlying System.Threading.Timer to a dueTime of -1 which denotes infinity). That means that any continuations set on that task will never execute, and any poor thread that happens to .Wait() on that Task will forever be blocked.

What possible use can a Task that never completes have? Would anyone expect such a return value? Shouldn't any negative value passed to .Delay(), including values in that special range, throw an ArgumentOutOfRangeException?

like image 817
Allon Guralnek Avatar asked May 24 '12 16:05

Allon Guralnek


People also ask

Does task delay block?

Task. Delay() is asynchronous. It doesn't block the current thread.

Does task delay create a new thread?

Task. Delay does not create new Thread, but still may be heavy, and no guaranties on order of execution or being precise about deadlines.

Does task delay block the thread?

Delay(1000) doesn't block the thread, unlike Task. Delay(1000). Wait() would do, more details.

What does Task delay do C#?

Delay(Int32) Creates a task that completes after a specified number of milliseconds.


1 Answers

Timeout.Infinite or -1 is useful when you want to wait indefinitely for a long-running task that will take an indeterminate amount of time to complete, but will eventually complete.

The Win32 API also uses a constant INFINITE = -1 for infinite timeouts.

You wouldn't normally want to use it in a UI thread, as it could freeze the UI (which seems to be your problem). But there are valid use cases in a worker thread - e.g. a server that is blocking waiting for a connection from a client.

like image 138
Joe Avatar answered Sep 29 '22 03:09

Joe