How do I run tasks in parallel and select the first result that satisfies a given condition in C#? [duplicate]

痞子三分冷 提交于 2019-11-30 22:34:17
Douglas

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;
}

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.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!