c# - Windows 窗体并行绘图

标签 c# winforms graphics parallel-processing runtime-error

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

在使用graphahics.FillRectangle()的线上,当我尝试时,我不断收到此错误:

An exception of type 'System.InvalidOperationException' occurred in System.Drawing.dll but was not handled in user code

Additional information: Object is currently in use elsewhere.

这是我正在使用的代码:

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

我认为发生的情况是图形对象无法同时处理多个调用。有没有办法解决?我尝试在每个并行调用中创建对图形对象的本地引用,但这不起作用。

最佳答案

Is it possible to draw on a panel using a Parallel.For loop?

不,没有任何实际有用的方式。

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

GDI+ 对象,例如您的 Graphics 对象(您没有说明从哪里获得该对象,但人们希望它是在 PaintEventArgs 中传递给您的……如果没有,你的代码中有其他设计缺陷)可以更宽容,但不是线程安全的。您可以围绕对象的实际使用添加同步,但这些使用是缓慢的部分。序列化它们将抵消代码中并发的大部分好处。

您的问题并没有明确说明您在此处使用Parallel是否是解决某些特定性能问题的实际尝试,而不管该问题实际上是什么。 Stack Overflow 上有许多问题及其答案,讨论了提高 Windows 窗体代码渲染性能的各种技术。

一般来说,这些技术中的大多数都涉及尽可能减少缓存完成的工作总量。根据您所显示的代码,您可能至少需要执行两件事:

  1. 缓存矩形和颜色的计算。每当基础参数发生变化时,您甚至可以使用Parallel来完成这部分计算。
  2. 将所有内容绘制到 Bitmap 对象中。这必须在单线程中完成,但是 a) 不必在拥有 UI 对象的 UI 线程中完成,b) 无论何时底层参数发生变化,您(再次)都可以只执行一次。绘制到 Bitmap 后,您可以在发生 Paint 事件时绘制 Bitmap 对象,而不必重新渲染所有内容从头开始。

关于c# - Windows 窗体并行绘图,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43289306/

相关文章:

c# - 在 unity 2D 中制作跳跃脚本时无法使 rb.velocity 工作

c# - 我要疯了吗? C#/静态修饰符

c# - 只允许文本框中的特定字符

C# 控制台不断弹出表单应用程序

java - 将物体从墙上弹起

c# - 带变量名的迭代

c# - 计算 MP3 帧的长度(以毫秒为单位)

java - 卡在 Java Swing 项目 : Conway's Game of Life

c# - 如何在简单的油漆应用中清除面板

c++ - 有据可查、开源且快速的 C/C++ 图像处理库。比如 'resize' ,旋转,变色,裁剪