TPL wait for task to complete with a specific return value

前端 未结 2 805
醉话见心
醉话见心 2020-12-10 14:58

I\'d like to make a request to X different web services who will each return either true or false.

These tasks should be executed in parall

相关标签:
2条回答
  • 2020-12-10 15:38

    One option is to use Reactive Extensions. Lets assume that you have a collection of tasks. It could be the tasks you mentioned in the question:

    var tasks = new[] { t1, t2, t3 };
    

    To execute the tasks in parallel and returning when the first tasks returns true you use this expression:

    var result = await tasks
      .Select(t => t.ToObservable())
      .Merge()
      .FirstOrDefaultAsync(success => success);
    

    The tasks are converted into observable sequences that each "fire" once when the task completes. These sequences are then merged into a single sequence which then is "converted" back into something that can be awaited using a predicate. And if necessary you can use a more complicated predicate instead of success => success.

    After this you can cancel the remaining unfinished tasks if you are using a CancellationTokenSource:

    cts.Cancel();
    

    The variable result will now be either true or false and any remaining tasks have been given a signal to cancel.

    If you want to test this with your sample tasks you will have to modify them slightly to use Task.Delay instead of Thread.Sleep to enable the task to be cancelled:

    var t1 = Task.Run<bool>(async () =>
    {
        await Task.Delay(TimeSpan.FromSeconds(1), cts.Token);
        Console.WriteLine("Task 1 Excecuted");
        return false;
    }, cts.Token);
    
    0 讨论(0)
  • 2020-12-10 16:00

    You can simply use Task.WhenAny and a predicate multiple times until the "right" task comes along

    async Task<T> WhenAny<T>(IEnumerable<Task<T>> tasks, Func<T, bool> predicate)
    {
        var taskList = tasks.ToList();
        Task<T> completedTask = null;
        do
        {
            completedTask = await Task.WhenAny(taskList);
            taskList.Remove(completedTask);
        } while (!predicate(await completedTask) && taskList.Any());
    
        return completedTask == null ? default(T) : await completedTask;
    }
    
    0 讨论(0)
提交回复
热议问题