C#并行运行任务,并将每个任务与输入关联

时间:2019-08-08 20:57:35

标签: c# asynchronous parallel-processing task task-parallel-library

public class Input
{
    public bool ParameterOne { get; set; }
    public string ParameterTwo { get; set; }
}

我有一个List<Input>,我想并行处理,使输入与输出关联。我遍历此列表以构建Task

var results = new List<(Input, Output)>();
foreach (var input in inputs)
{
    Output output = await Process(input);
    results.Add((input, output));
}

但这不是并行运行的。我想要它。

var inputsAndTasks = new List<(Input Input, Task<Output> OutputTask)>();
foreach (var input in inputs)
{
    Task<Output> output = Process(input);
    inputsAndTasks.Add((input, output));
}
Output[] results = await Task.WhenAll(inputsAndTasks.Select(i => i.OutputTask));
// results are no longer associated with their inputs!

如何并行运行它,但保留输入与输出的关联?我不想使输入成为输出上的对象。

2 个答案:

答案 0 :(得分:1)

有另一种方法可以通过利用“ AsParallel”来避免完全使用任务。

IList<Input> inputs = new List<Input>();
// populate inputs here

IDictionary<Input, Output> associations = new Dictionary<Input, Output>();
associations.AddRange(inputs.AsParallel()
                        .Select(async i => 
                            { Output o = await Process(i); 
                              return new KeyValuePair<Input, Output>(i, o);
                            }));

答案 1 :(得分:0)

您可以等待WhenAll,然后执行循环以匹配输入和输出

var inputsAndTasks = new List<(Input Input, Task<Output> OutputTask)>();
foreach (var input in inputs)
{
    Task<Output> output = Process(input);
    inputsAndTasks.Add((input, output));
}

await Task.WhenAll(inputsAndTasks.Select(i => i.OutputTask));

var results = new List<(Input, Output)>();
foreach (var x in inputsAndTasks)
{
    Output output = await x.OutputTask;
    results.Add((x.Input, output));
}

由于您已经知道所有单独的输出任务均已完成,因此在第二个循环中执行await将立即返回结果。