如何并行运行任务并选择满足C#中给定条件的第一个结果? [英] How do I run tasks in parallel and select the first result that satisfies a given condition in C#?

查看:102
本文介绍了如何并行运行任务并选择满足C#中给定条件的第一个结果?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我希望并行执行三个任务。我希望检查完成的第一个任务的结果,并进行检查以确定结果是否。如果是,我将取消所有其他任务并返回此结果,否则,我将等待下一个完成的任务,并检查该任务是否 good ,如果是,则执行相同的操作。 (以为对OutputDataType成员进行一些简单的检查就可以认为它们是。)

There are three tasks that I wish to run in parallel. I wish to examine the result of the first task that finished and do a check to decide if the result is good. If yes, I cancel all other tasks and return this result, if not, I will wait for next completed task and check if that is good and do the same if it is. (Think of being good as some simple check on a member of OutputDataType).

我继续执行此操作,直到获得带有 good 结果,或者所有任务返回的结果都不是 good ,在这种情况下,我返回 null

I continue this until I obtain a completed task with a good result, or all tasks return with results that are not good, in which case I return null.

谢谢。

using System;
using System.Threading;
using System.Threading.Tasks;
namespace myNamespace
{
    class Program
    {
        static void Main()
        {
            InputDataType data = getMyData();
            OutputDataType x = Foo(data);
        }   

        static OutputDataType Foo(InputDataType data)
        {
            Task<OutputDataType> task1 = null, task2 = null, taks3 = null;
            Task<OutPutDataType>[] TaskArray = { task1, task2, task3 };

            task1 = Task<SolutionInterpreters>.Factory.StartNew(() => RunFunc1(data));
            task2 = Task<SolutionInterpreters>.Factory.StartNew(() => RunFunc2(data));
            task3 = Task<SolutionInterpreters>.Factory.StartNew(() => RunFunc3(data));

            /*
            .
            .
            .
            */
        }
    }
}


推荐答案

在TPL中,任务取消是协作的,因此您需要定义一些方法来向您的其他任务指示它们应该停止执行。最常见的方法是通过 CancellationTokenSource ,可以在您的 RunFuncX 方法中检查其令牌是否已取消。

In TPL, task cancellation is cooperative, so you need to define some means of indicating to your other tasks that they should stop executing. The most common way to do this is through CancellationTokenSource, whose token can be checked for cancellation within your RunFuncX methods.

static void Main()
{
    InputDataType data = getMyData();
    OutputDataType x = Foo(data).Result;
}   

static async Task<OutputDataType> Foo(InputDataType data)
{
    // Spawn your tasks, passing the cancellation token.
    var cts = new CancellationTokenSource();
    var task1 = Task.Factory.StartNew(() => RunFunc1(data, cts.Token));
    var task2 = Task.Factory.StartNew(() => RunFunc2(data, cts.Token));
    var task3 = Task.Factory.StartNew(() => RunFunc3(data, cts.Token));
    var tasks = new [] { task1, task2, task3 };

    // Loop while tasks are running.
    while (tasks.Any())
    {
        // Wait for any task to complete.
        var completedTask = await Task.WhenAny(tasks);

        // If its result is good, indicate cancellation to the other tasks,
        // and return the result.
        if (IsResultGood(completedTask.Result))
        {
            cts.Cancel();
            return completedTask.Result;
        }

        // Otherwise, remove the completed task from the array,
        // and proceed to the next iteration.
        tasks = tasks.Where(t => t != completedTask).ToArray();
    }

    // No good results.
    return null;
}

根据Spo1ler的评论,我已经更新了您的 Foo 方法实现异步实现。假设您使用的是C#5.0。使用该方法时,请使用 await 来获取其结果。如果您确实是在作为控制台应用程序运行,则您的最顶层调用将需要阻止,因此您只需获取任务的结果

Per Spo1ler's comment, I've updated your Foo method to an asynchronous implementation. This assumes you're using C# 5.0. When consuming the method, use await to get its result. If you're really running as a console application, your topmost call would need to block, so you can just get the task's Result.

这篇关于如何并行运行任务并选择满足C#中给定条件的第一个结果?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆