Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Task.Delay for more than int.MaxValue milliseconds

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));
like image 704
Phil K Avatar asked Jan 17 '15 01:01

Phil K


3 Answers

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;
    }
}
like image 122
i3arnon Avatar answered Oct 16 '22 15:10

i3arnon


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); 
}
like image 3
Mike Zboray Avatar answered Oct 16 '22 13:10

Mike Zboray


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.

like image 3
Peter Duniho Avatar answered Oct 16 '22 15:10

Peter Duniho