2017-04-08 94 views
1

是否可以使用Parallel.For循环绘制面板?我有一个多维数组double,double[][] plants,我想并行绘制列,其中数组中的每个条目在面板上的网格中绘制为矩形。Windows窗体并行绘图

在有grapahics.FillRectangle()行了,当我尝试我不断收到此错误:

“System.InvalidOperationException”类型的异常出现在System.Drawing.dll程序,但在用户代码中没有处理

附加信息:对象当前正在其他地方使用。

这里是我使用的代码:

Parallel.For(0, simWidth, i => 
     { 
      Color plantColor; 
      RectangleF plantRectangle= new Rectangle(); 
      SolidBrush plantBrush = new SolidBrush(Color.Black); 
      for (int j = 0; j < simHeight; ++j) 
      { 
       int r, g = 255, b; 
       r = b = (int)(255 * (Math.Tanh(simulation.plants[i, j]) + 1)/2.0); 
       plantColor = Color.FromArgb(100, r, g, b); 
       plantBrush.Color = plantColor; 
       plantRectangle.Location = new PointF(i * cellSize, j * cellSize); 
       graphics.FillRectangle(plantBrush, plantRectangle); 
      } 

      plantBrush.Dispose(); 
     }); 

我认为正在发生的事情是,图形对象一下子无法处理多个呼叫。有没有办法解决?我试图在每次并行调用中创建一个对图形对象的本地引用,但没有奏效。

回答

2

是否可以使用Parallel.For循环在面板上绘图?

不,不以任何方式实际上有用。

UI对象(例如Panel)具有“线程关联”。也就是说,它们属于特定的线程,并且只能在该线程中使用。

GDI +的对象,如您Graphics对象(你不说你得到了这个对象,但人们希望它传递给你PaintEventArgs&hellip;如果没有,你在你的代码中的其他设计缺陷)可以更宽容,但不是线程安全的。您可以围绕对象的实际用途添加同步,但这些用途是缓慢的部分。对它们进行序列化将会否定代码中并发性的大部分好处。

你的问题并没有说明你在这里使用Parallel是否是解决某些特定性能问题的实际尝试,不用关心这个问题实际上是什么。有许多关于Stack Overflow的问题,讨论了用于改进Windows Forms代码中的呈现性能的各种技术。

一般来说,这些技术大多涉及尽可能减少缓存完成的工作量。根据您显示的代码,至少有两件事您可能想要做:

  1. 缓存矩形和颜色的计算。只要底层参数发生变化,您甚至可以使用Parallel执行计算的那部分。
  2. 将一切画成Bitmap对象。这必须单线程完成,但是a)它不必在拥有UI对象的UI线程中完成,b)只要底层参数发生变化,您就可以再次执行此操作。在绘制成Bitmap后,您可以在发生Paint事件时绘制Bitmap对象,而不必从头开始重新渲染所有内容。
+0

'graphics'来自'PaintEventArgs e','e.Graphics'。我正在寻求平行,因为它本质上是“呈现”我的模拟。缓存和使用“位图”听起来像是个好主意,谢谢! –