迭代每个Enum值需要并行化

时间:2012-11-22 01:47:11

标签: c# .net enums task-parallel-library

在并行通话中我做错了什么?

static void Main(string[] args)
{
    TasteAll<HotCupOf>(TurnCoffeeVenMachineOn);
}

public static void TasteAll<Mode>(Action<Mode> Make)
{
    foreach (Mode mode in Enum.GetValues(typeof(Mode)))
    {
        Task.Factory.StartNew(() => Make(mode) );
        //Make(mode); //<-- Works Fine with normal call
    }
    Console.ReadLine();
}

enum HotCupOf
{
    Black,
    Latte,
    Cappuccino,
    Mocha,
    Americano,
    Espresso,
    Chocolate,
    Tea
}

public static void TurnCoffeeVenMachineOn(HotCupOf SelectedDrink)
{
    Console.WriteLine(SelectedDrink);
}

3 个答案:

答案 0 :(得分:5)

你已经关闭了一个循环变量。您正在启动的每个任务都引用了相同的闭合变量,该变量在迭代集合时会发生变化。

你需要这样的东西:

public static void TasteAll<Mode>(Action<Mode> Make)
{
        foreach (Mode mode in Enum.GetValues(typeof(Mode)))
        {
            Mode localMode = mode;
            Task.Factory.StartNew(() => Make(localMode) );
            //Make(mode); //<-- Works Fine with normal call
        }
    Console.ReadLine();
}

使用C#5,循环变量现在在语义上位于循环块内部,因此这是不必要的。有关其他讨论,请参阅Eric Lippert的blog

答案 1 :(得分:2)

一个例子:

    enum Gender{
        male,
        female
    }        

    Parallel.ForEach((Gender[])Enum.GetValues(typeof(Gender)), gender=>
                {
                    Console.WriteLine(gender.ToString()) // example: code goes here
                });

含义: 对于每个性别性别,请在{}之间异步执行代码。

答案 2 :(得分:1)

如果您希望循环阻止,您还可以考虑使用Parallel.ForEach来解决此问题。它使用分区程序将您的集合分发到工作项中,然后比为每次迭代创建新的Task更有效地执行它们。这实际上取决于Make调用的重要程度以及迭代越多越好。

public static void TasteAll<Mode>(Action<Mode> Make)
{
        Parallel.ForEach(Enum.GetValues(typeof(Mode)), mode =>
        {
            Mode localMode = mode;
            Make(mode);
        });

    Console.ReadLine();
}