SnapADragon
SnapADragon

Reputation: 535

Task.Delay() with long delay in Xamarin.iOS

I have a specific requirement where I have to invoke a background thread after varying interval of time in Xamarin.iOS endlessly. I first tried to implement it using Timer class as explained in this page, but I could not vary the time interval indefinite number of times.

So, I have implemented below solution:

void SomeUIMethod()
{
    while (true)
    {
        await Task.Run(PerformSync);
    }
}
...
private async Task PerformSync()
{
    var newInterval = SomeBackgroundTask();
    Task.Delay(newInterval*1000).Wait();
}

This will invoke the next thread after the new time interval as I expected.

Now, my queries as below:

  1. Is there any other way of achieving this by not having the Thread in delayed state most of the time?
  2. Does it hamper App performance in any manner? considering that there would be atmost one background Thread in delayed state.

Upvotes: 1

Views: 2103

Answers (1)

Paul Turner
Paul Turner

Reputation: 39615

Task.Wait() is not a method you want to use when you have any alternatives. It synchronously blocks the asynchronous operation, consuming the thread and possibly deadlocking the UI.

Instead, you can await the Task:

private async Task PerformAsync()
{
    while(true)
    {
        var newInterval = SomeBackgroundTask();
        await Task.Delay(newInterval * 1000);
    }
}

This will loop indefinitely, with a delay between loops, but the thread is released after every loop.

Additionally, it's often problematic to have something loop forever. You probably want to it to stop at some point. This is a good candidate for using a CancellationToken to indicate you want to abandon the loop.

private async Task PerformAsync(CancellationToken cancellationToken)
{
    try 
    {
        while(!cancellation.IsCancellationRequested)
        {
            var newInterval = SomeBackgroundTask();
            await Task.Delay(newInterval * 1000, cancellationToken);
        }
    }
    catch (OperationCanceledException ex) when (cancellation.IsCancellationRequested)
    {
        // Swallow the exception and exit the method.
    }
}

Upvotes: 1

Related Questions