The maximum duration a Task.Delay
can be told to delay is int.MaxValue
milliseconds. What is the cleanest way to create a Task
which will delay beyond that time?
// Fine.
await Task.Delay(TimeSpan.FromMilliseconds(int.MaxValue));
// ArgumentOutOfRangeException
await Task.Delay(TimeSpan.FromMilliseconds(int.MaxValue + 1L));
You can't achieve that using a single Task.Delay
since it internally uses a System.Threading.Timer
that only accepts an int.
However you can do that using multiple waits one after the other. Here's the cleanest way:
static async Task Delay(long delay)
{
while (delay > 0)
{
var currentDelay = delay > int.MaxValue ? int.MaxValue : (int) delay;
await Task.Delay(currentDelay);
delay -= currentDelay;
}
}
You can easily write a method to break it down into smaller delays:
private static readonly TimeSpan FullDelay = TimeSpan.FromMilliseconds(int.MaxValue);
private static async Task LongDelay(TimeSpan delay)
{
long fullDelays = delay.Ticks / FullDelay.Ticks;
TimeSpan remaining = delay;
for(int i = 0; i < fullDelays; i++)
{
await Task.Delay(FullDelay);
remaining -= FullDelay;
}
await Task.Delay(remaining);
}
You can delay multiple times. For example:
static async Task LongDelay(long milliseconds)
{
if (milliseconds < 0)
{
throw new ArgumentOutOfRangeException();
}
if (milliseconds == 0)
{
return;
}
int iterations = (milliseconds - 1) / int.MaxValue;
while (iterations-- > 0)
{
await Task.Delay(int.MaxValue);
milliseconds -= int.MaxValue;
}
await Task.Delay(milliseconds);
}
That said, int.MaxValue
milliseconds is a really long time, almost 25 days! IMHO a much more important question is, is the Task.Delay()
method really the best solution for your scenario? Knowing more about why you are trying to wait for such a long period of time might help others offer you a better solution to the actual problem, instead of addressing this very specific need.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With