在并行通话中我做错了什么?
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);
}
答案 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();
}