3

What am I doing wrong in the parallel call?

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

You've closed over a loop variable. Each Task you are starting has a reference to the same closed over variable, which is changing as you iterate the collection.

You need something like this:

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

With C# 5, loop variables are now semantically inside of the loop block, so this is unnecessary. See Eric Lippert's blog for additional discussion.

于 2012-11-22T01:54:49.373 に答える
3

An example:

    enum Gender{
        male,
        female
    }        

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

Meaning: For each Gender gender, execute code between { } asynchronously.

于 2017-06-19T22:09:04.697 に答える
1

If you want the loop to block you could also consider using Parallel.ForEach for this problem. It uses a Partitioner to distribute your collection into work items and then executes them way more efficiently than if you create a new Task for each iteration. This is really does depend on how heavy your Make calls are and also the more iterations the better.

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 に答える