繁体   English   中英

Windows窗体并行绘图

[英]Windows Forms Parallel Drawing

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

grapahics.FillRectangle()的行上,尝试进行时,我不断收到此错误:

System.Drawing.dll中发生类型为'System.InvalidOperationException'的异常,但未在用户代码中处理

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

这是我正在使用的代码:

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

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

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

不,实际上没有任何用处。

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

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

您的问题并不清楚您是否在此处使用Parallel甚至是解决某些特定性能问题的实际尝试,也不要介意该问题实际上是什么。 关于Stack Overflow的答案有很多问题,讨论了用于改善Windows Forms代码中呈现性能的各种技术。

通常,大多数这些技术都涉及通过尽可能多地缓存来减少完成的工作总量。 根据显示的代码,您可能至少要做两件事:

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM