有没有办法运行时有条件地并行生成匿名类型的查询?

时间:2014-04-07 23:18:20

标签: c# task-parallel-library

编辑:主要在下面解决。然而,另外一件我很好奇的事情(为了改善google-fu的未来是 - 你会怎么说这个问题?我知道我的标题有点奇怪但是想不出更简洁的总结方法欢迎提出意见中的建议。

假设我的工作流程涉及潜在的昂贵选择。在运行时,我希望能够选择是否使其并行。

更好地解释。考虑一下这个问题(破解代码 - 做什么 - 我想要的不是我说的话):

void Main()
{
    bool runTimeParallelOption = false; // assume this option comes from e.g. user/config

    var j = Enumerable.Range(1,5);

    if (runTimeParallelOption)
        j = j.AsParallel();

    var results = j.Select(x => 
    {
        Thread.Sleep(1000);
        return new { Number = x, Square = x * x };
    });

    var sw = Stopwatch.StartNew();
    foreach (var result in results)
        Console.WriteLine(result.Square);

        Console.WriteLine("Elapsed: : " + sw.Elapsed);
}

这里的希望是,如果设置runTimeParallelOption,它将使查询并行。但显然(事后看来!)这不起作用,因为j的类型意味着我仍在执行IEnumerable扩展方法。

如果你不介意重构使{ Number = x, Square = x * x }成为一流的类型,那么解决这个问题是微不足道的,但这对我来说并不是很有吸引力。有没有办法让我的蛋糕吃掉它?

2 个答案:

答案 0 :(得分:1)

我认为最简单的选择就是始终使用AsParallel()。然后,如果您不想并行化,请添加WithDegreeOfParallelism(1)

答案 1 :(得分:0)

受到this的启发,我提出的最好的是:

void Main()
{
    bool runTimeParallelOption = true; // assume this option comes from e.g. user/config

    var j = Enumerable.Range(1,5);

    var results = Enumerable.Empty<int>().Select(x => new { Number = (int)0, Square = (int)0 }).Take(0);

    var mutate = InferredProjection(1, results.FirstOrDefault(),  x => { Thread.Sleep(1000); return new { Number = x, Square = x * x }; });

    var sw = Stopwatch.StartNew();
    if (runTimeParallelOption)
        results = j.AsParallel().Select(mutate);
    else
        results = j.Select(mutate);
    sw.Stop();

    foreach (var result in results)
        Console.WriteLine(result.Square);

    Console.WriteLine("Elapsed: : " + sw.Elapsed);
}


static Func<T, U> InferredProjection<T, U>(T infer1, U infer, Func<T, U> project)
{
    return project;
}