并行运行多个任务,如果其中任何一个返回false .net,则取消休息

发布于 2025-02-03 08:16:57 字数 940 浏览 2 评论 0 原文

目前,我有一个类似的代码:

 bool task1Result = await RunTask1(data);
 if(!task1Result)
     return false;

 bool task2Result = await RunTask2(data);
 if(!task2Result)
     return false;

 bool task3Result = await RunTask3(data);
 if(!task3Result)
     return false;

 bool task4Result = await RunTask4(data);
 if(!task4Result)
     return false;

添加的示例:

private async Task<bool> RunListOfTasks() {
CancellationTokenSource cts = new CancellationTokenSource();
CancellationToken ct = cts.Token;

var tasks = new List<Task<bool>> { RunTask1(data, ct), RunTask2(data, ct), RunTask3(data, ct), RunTask4(data, ct) };
while (tasks.Any())
{
    var currentTask = await Task.WhenAny(tasks);
    if (!await currentTask)
    {
        ct.Cancel();
        return false;
    }
    tasks.Remove(currentTask);
}
return true;
}

是否可以并行运行所有这些代码,如果其中一个失败(类似于结果为false),然后停止处理其余的并返回。谢谢

Currently I have a code like this:

 bool task1Result = await RunTask1(data);
 if(!task1Result)
     return false;

 bool task2Result = await RunTask2(data);
 if(!task2Result)
     return false;

 bool task3Result = await RunTask3(data);
 if(!task3Result)
     return false;

 bool task4Result = await RunTask4(data);
 if(!task4Result)
     return false;

Added sample:

private async Task<bool> RunListOfTasks() {
CancellationTokenSource cts = new CancellationTokenSource();
CancellationToken ct = cts.Token;

var tasks = new List<Task<bool>> { RunTask1(data, ct), RunTask2(data, ct), RunTask3(data, ct), RunTask4(data, ct) };
while (tasks.Any())
{
    var currentTask = await Task.WhenAny(tasks);
    if (!await currentTask)
    {
        ct.Cancel();
        return false;
    }
    tasks.Remove(currentTask);
}
return true;
}

Is it possible to run all of them in parallel and if one of them fails (like result is false), then stop processing the rest and return. Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

信愁 2025-02-10 08:16:57

task.whenany -in-a-loop是generally considered an antipattern, because of its

包装任务的一种简单方法是选择 linq运算符:

private async Task<bool> RunListOfTasks()
{
    using CancellationTokenSource cts = new();

    List<Task<bool>> tasks = new()
    {
        RunTask1(data, cts.Token),
        RunTask2(data, cts.Token),
        RunTask3(data, cts.Token),
        RunTask4(data, cts.Token),
    };

    Task<bool>[] enhancedTasks = tasks.Select(async task =>
    {
        try
        {
            bool result = await task.ConfigureAwait(false);
            if (!result) cts.Cancel();
            return result;
        }
        catch (OperationCanceledException) when (cts.IsCancellationRequested)
        {
            return false;
        }
    }).ToArray();

    bool[] results = await Task.WhenAll(enhancedTasks).ConfigureAwait(false);
    return results.All(x => x);
}

The Task.WhenAny-in-a-loop is generally considered an antipattern, because of its O(n²) complexity. The preferred approach is to wrap your tasks in another set of tasks, that will include the functionality of canceling the CancellationTokenSource when the result is false. Then await the wrapper tasks instead of the initial tasks, and propagate their result.

An easy way to wrap the tasks is the Select LINQ operator:

private async Task<bool> RunListOfTasks()
{
    using CancellationTokenSource cts = new();

    List<Task<bool>> tasks = new()
    {
        RunTask1(data, cts.Token),
        RunTask2(data, cts.Token),
        RunTask3(data, cts.Token),
        RunTask4(data, cts.Token),
    };

    Task<bool>[] enhancedTasks = tasks.Select(async task =>
    {
        try
        {
            bool result = await task.ConfigureAwait(false);
            if (!result) cts.Cancel();
            return result;
        }
        catch (OperationCanceledException) when (cts.IsCancellationRequested)
        {
            return false;
        }
    }).ToArray();

    bool[] results = await Task.WhenAll(enhancedTasks).ConfigureAwait(false);
    return results.All(x => x);
}
云淡月浅 2025-02-10 08:16:57

Microsoft的反应性框架以一种非常好的方式来做到这一点:

bool[] result =
    await 
        Observable
            .Merge(
                Observable.FromAsync(ct => RunTask1(data, ct)),
                Observable.FromAsync(ct => RunTask2(data, ct)),
                Observable.FromAsync(ct => RunTask3(data, ct)),
                Observable.FromAsync(ct => RunTask4(data, ct)))
            .TakeUntil(x => x == false)
            .ToArray();

它返回所有结果,直到一个任务返回 false

Microsoft's Reactive Framework does this in a very nice way:

bool[] result =
    await 
        Observable
            .Merge(
                Observable.FromAsync(ct => RunTask1(data, ct)),
                Observable.FromAsync(ct => RunTask2(data, ct)),
                Observable.FromAsync(ct => RunTask3(data, ct)),
                Observable.FromAsync(ct => RunTask4(data, ct)))
            .TakeUntil(x => x == false)
            .ToArray();

It returns all of the results that come in right up to the point one of the tasks returns a false.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文