3

我在并行调用中做错了什么?

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

3 回答 3

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 的博客

于 2012-11-22T01:54:49.373 回答
3

一个例子:

    enum Gender{
        male,
        female
    }        

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

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

于 2017-06-19T22:09:04.697 回答
1

如果您希望循环阻塞,您也可以考虑使用Parallel.ForEach这个问题。Task它使用 Partitioner 将您的集合分配到工作项中,然后以比为每次迭代创建新的方式更有效地执行它们。这确实取决于您的Make调用量以及迭代次数越多越好。

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

    Console.ReadLine();
}
于 2012-11-22T06:37:43.953 回答