2
votes

I am implementing a new feature in already existing application and would like to know how best I can achieve the following:

  1. Create two tasks.
  2. Start them in parallel.
  3. Await and wait for one of them to complete.
  4. Once one of them completes, spun a timer for t seconds before returning the response. This is done because one of the task might run for a longer time than another.

I have the solution of #1 to #3 but #4.

List<Task> tasks = new List<Task>(length);
tasks.Add(CreateTask(get_data_source));
await Task.WhenAny(tasks);

I don't want to provide any timeout in #3. But I would like to wait till the completion of a task and then trigger a timer for t seconds. After t seconds, return the result (if both completed, then both else just the completed task).

3
await Task.Delay(...)?canton7
not really clear about what you exactly want. If both tasks finish at the same time, then just return both results ?=! and if 1 of them finishes earlier then wait a whil before returnin the response?Mong Zhu
do you have any means to know which task will finish first?Mong Zhu

3 Answers

4
votes

After first task complete, you can await for any of remaining tasks or delay task to complete .

This will give you possibility to await 5 seconds for other tasks to complete, if not, then return result.

var tasks = new List<Task>
{
    CreateTask(get_data_source),
    CreateTask(get_data_source2)
};

var completedTask = await Task.WhenAny(tasks);

await Task.WhenAny(Task.WhenAll(tasks), Task.Delay(5000));

// Return result
0
votes

This might be a good place for Task.WhenAll(). It will return when all of the tasks are completed. That way you can just wait for all of the tasks to respond instead of just waiting for an amount of time.

https://docs.microsoft.com/en-us/dotnet/api/system.threading.tasks.task.whenall?view=netframework-4.8

0
votes

Another example, using a CancellationToken and CancellationTokenSource.CancelAfter

var ts = new CancellationTokenSource();

var list = Enumerable.Range(0, 4)
                     .Select(x => DoStuff(ts.Token))
                     .ToList();

await Task.WhenAny(list);

ts.CancelAfter(1000);

await Task.WhenAll(list);

This will help if your tasks are using CancellationTokens to help shut them down gracefully