C#.net多线程

我正在尝试使用C#.net在一个名为Grasshopper(Rhino3D的一部分)的包中优化一些数学运算.操作非常简单,但必须执行的列表很大,可能会变得更大.

我正在使用Parallel.ForEach,并在我的C#脚本中列出我得到的最终结果的数量低于预期的数量.这很可能是因为list.add不是线程安全的(或者在我正在构建它的软件中线程安全)的事实.

  private void RunScript(double z, int x, List<double> y, ref object A)
  {
    List<double> temp = new List<double>();
    double r;
    System.Threading.Tasks.Parallel.ForEach(y, numb =>
      {
      r = Math.Pow((numb * x), z);
      temp.Add(r);
      });
    A = temp;

请帮助我找出一种简单而有效的方法,使用CPU多线程(或如果您有关于GPU CUDA的建议)运行这个简单的数学运算数百个数值.

我希望这个模糊和具体的软件不会打扰你,因为据我所知,它与正常的C#.Net / Python / VB.Net相同.

你猜出来,列表< T>不是线程安全的.您必须同步其任何实例的访问.

一个选项是在每个任务中简单同步:

private void RunScript(double z, int x, List<double> y, ref object A)
{
    List<double> temp = new List<double>();
    object l = new object();
    System.Threading.Tasks.Parallel.ForEach(y, numb =>
    {
      double r = Math.Pow((numb * x), z);
      lock (l) temp.Add(r);
    });
    A = temp;
}

注意:你的代码还有另一个错误.您在所有任务中共享相同的r变量,这可能导致相同的值被添加两次或更多次,而其他值被忽略.我通过简单地将变量声明移到用于ForEach()调用的匿名方法的正文来修复错误.

另一个选择是认识到你提前知道你将有多少结果,因此可以简单地初始化一个足够大的数组来包含所有的结果:

private void RunScript(double z, int x, List<double> y, ref object A)
{
    double[] results = new double[y.Count];
    System.Threading.Tasks.Parallel.For(0, y.Count, i =>
    {
      // read-only access of `y` is thread-safe:
      results[i] = Math.Pow((y[i] * x), z);
    });
    A = new List<double>(results);
}

没有两个线程将尝试访问结果数组中的相同元素,并且数组本身永远不会改变(即重新分配),因此这是完全线程安全的.

上面假设你确实需要一个List< double>作为输出对象.当然,如果一个数组令人满意,那么你可以将结果分配给A,而不是把它传给List< T>构造函数在最后创建一个全新的对象.

翻译自:https://stackoverflow.com/questions/29709857/c-net-multithreading

转载注明原文:C#.net多线程