c#多个任务不能并行运行
我试图创建一个多线程的骰子滚动模拟 - 只是为了好奇心,多线程化的前进的喜悦,并向其他人展示了“随机结果”的效果(许多人无法理解,如果你连续六次掷骰子掷骰子,你已经有1,2,3,4,5,下一卷不是6.)。 为了向他们展示m个骰子的n个卷的分布,我创建了这个代码。
那么,结果是好的,但即使我为每个骰子创建一个新的任务程序运行单线程。 多线程将是合理的,以模拟6百万或更多骰子的“数百万”重播,因为结束时间将快速增长。
我从msdn中读到了几个例子,它们都表明应该有几个同时运行的任务。 有人可以给我一个提示,为什么这个代码不使用很多线程/内核? (甚至没有,当我试图一次运行400个骰子和1000万卷时)
起初,我初始化存储结果的锯齿状数组。 第一维度:每个骰子1个入口,第二个维度将是每个骰子滚动的眼睛分布。
接下来,我创建了一组任务,每个任务返回结果数组(第二个维度,如上所述)每个数组都有6个条目,分别代表laplace W6骰子的每个边。 如果骰子掷出1眼,则第一个输入[0]增加+1。 因此,您可以查看每个值的滚动频率。
然后我使用一个简单的for-loop来启动所有线程。 没有任何迹象表明等到一个线程,直到所有开始。
最后,我等待所有人完成并总结结果。 如果改变,它没有任何区别
Task.WaitAll(任务); Task.WhenAll(任务);
我的问题再次说明:为什么代码不使用我的CPU的多个核心? 我需要改变什么?
提前致谢!
代码如下:
private void buttonStart_Click(object sender, RoutedEventArgs e)
{
int tries = 1000000;
int numberofdice = 20 ;
int numberofsides = 6; // W6 = 6
var rnd = new Random();
int[][] StoreResult = new int[numberofdice][];
for (int i = 0; i < numberofdice; i++)
{
StoreResult[i] = new int[numberofsides];
}
Task<int[]>[] tasks = new Task<int[]>[numberofdice];
for (int ctr = 0; ctr < numberofdice; ctr++)
{
tasks[ctr] = Task.Run(() =>
{
int newValue = 0;
int[] StoreTemp = new int[numberofsides]; // Array that represents how often each value appeared
for (int i = 1; i <= tries; i++) // how often to roll the dice
{
newValue = rnd.Next(1, numberofsides + 1); // Roll the dice; UpperLimit for random int EXCLUDED from range
StoreTemp[newValue-1] = StoreTemp[newValue-1] + 1; //increases value corresponding to eyes on dice by +1
}
return StoreTemp;
});
StoreResult[ctr] = tasks[ctr].Result; // Summing up the individual results for each dice in an array
}
Task.WaitAll(tasks);
// do something to visualize the results - not important for the question
}
}
这里的问题是tasks[ctr].Result
。 tasks[ctr].Result
。 的.Result
部本身等待功能到所得到的int数组存储到StoreResult之前完成。 相反,在Task.WaitAll
创建一个新的循环来获得结果。
您可以考虑执行一个Parallel.Foreach循环,而不是手动为此创建单独的任务。
正如其他人所指出的那样,当你试图对这个进行聚合时,你最终会等待每个单独的任务完成,所以这实际上并不是多线程的。
非常重要的注意事项: C#随机数生成器不是线程安全的(另请参阅此MSDN博客文章以便讨论该主题)。 不要在多个线程之间共享同一个实例。 从文档:
...随机对象不是线程安全的。 如果您的应用程序从多个线程调用Random方法,则必须使用同步对象来确保一次只有一个线程可以访问随机数生成器。 如果您不确保以线程安全的方式访问Random对象,则对返回随机数的方法的调用返回0。
另外,为了挑剔,使用Task
与多线程并不是一回事; 实际上,在这里您正在执行多线程,但也可以使用async / await来执行纯粹的异步,非多线程代码。 这主要用于I / O绑定操作,在这种操作中,创建单独的线程只是为了等待结果(但希望允许调用线程在等待结果时执行其他工作)是毫无意义的。
我认为在分配给主数组时,不应该担心线程的安全性(假设每个线程仅分配给数组中的特定索引,并且没有其他人分配给相同的内存位置)。 当多个线程同时访问/修改共享的可变状态时,您只需要担心锁定问题。 如果我正确阅读,这是可变状态(但它不是共享可变状态)。
链接地址: http://www.djcxy.com/p/52803.html