Search code examples
c#taskdelay

C# How to wait X seconds for a task to complete


I want to wait for a task to complete for a specified amount of time without blocking the thread and based on whether the task is complete or not perform some work.
e.g. waiting for an HTTP request for a specific amount of time.


Solution

  • In general you can use a CancellationTokenSource which will set the tokens IsCancellationRequested property to true if the period elapsed. Thus your code would be.

    public bool TrySomething(int sec)
    {
        var ct = new CancellationTokenSource(TimeSpan.FromSeconds(sec)).Token;
        var valueToReturne=false;
        while (!ct.IsCancellationRequested)
        {
            if (!MyCondition)
                        continue;
            else
                        valueToReturne = true;
        }
        return valueToReturne;
    }
    

    However, similar to the other solutions this is a busy loop meaning block your main thread.

    If you want you stop to program from not responding you would need to make your method async, e.g. by wrapping TrySomething in Task.Run, e.g.

    var ct = new CancellationTokenSource(TimeSpan.FromSeconds(sec)).Token;
    await Task.Run(() => TrySomething(ct), ct);
    
    public bool TrySomething(CancellationToken ct)
    {
        var valueToReturne=false;
        while (!ct.IsCancellationRequested)
        {
            if (!MyCondition)
                        continue;
            else
                        valueToReturne = true;
        }
        return valueToReturne;
    }
    

    However, this should only be done for CPU-bound work. But you are stating you want to check your internet connection, which is IO-bound work. You could still use Task.Run, but this is heavily frowned upon in this case. The optimal solution would be to use proper async methods for your internet connection check, e.g. if you are using Ping.Send to check for an internet connection, you should use Ping.SendAsync and so on.

    In this case your code would be:

    var ct = new CancellationTokenSource(TimeSpan.FromSeconds(sec)).Token;
    await TrySomething(ct);
    
    public async Task<bool> TrySomethingAsync(CancellationToken ct)
    {
        var valueToReturne=false;
        while (!ct.IsCancellationRequested)
        {
            if (!await MyConditionAsync(ct))
                        continue;
            else
                        valueToReturne = true;
        }
        return valueToReturne;
    }