简体   繁体   English

Windows窗体并行绘图

[英]Windows Forms Parallel Drawing

Is it possible to draw on a panel using a Parallel.For loop? 是否可以使用Parallel.For循环在面板上绘制? I have a multidimensional array of doubles, double[][] plants , and I want to draw the columns in parallel, where each entry in the array is drawn as a rectangle in a grid on the panel. 我有一个由doubles, double[][] plants的多维数组,我想并行绘制列,其中数组中的每个条目都在面板上的网格中绘制为矩形。

On the line with grapahics.FillRectangle() , I keep getting this error when I try: grapahics.FillRectangle()的行上,尝试进行时,我不断收到此错误:

An exception of type 'System.InvalidOperationException' occurred in System.Drawing.dll but was not handled in user code System.Drawing.dll中发生类型为'System.InvalidOperationException'的异常,但未在用户代码中处理

Additional information: Object is currently in use elsewhere. 附加信息:当前在其他地方使用对象。

Here is the code I am using: 这是我正在使用的代码:

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

I think what is happening is that the graphics object cannot handle multiple calls at once. 我认为正在发生的事情是图形对象无法一次处理多个调用。 Is there any way around this? 有没有办法解决? I tried creating a local reference to the graphics object in each parallel call but that did not work. 我尝试在每个并行调用中创建对图形对象的本地引用,但这没有用。

Is it possible to draw on a panel using a Parallel.For loop? 是否可以使用Parallel.For循环在面板上绘制?

No, not in any way that would actually be useful. 不,实际上没有任何用处。

UI objects, such as a Panel , have "thread affinity". UI对象(例如Panel )具有“线程相似性”。 That is, they are owned by a particular thread, and must only ever be used in that thread. 也就是说,它们由特定线程拥有,并且只能在该线程中使用。

GDI+ objects, like your Graphics object (you don't say where you got that object, but one hopes it was passed to you in PaintEventArgs …if not, you have other design flaws in your code) can be more forgiving, but are not thread-safe. GDI +对象,例如您的Graphics对象(您不说在哪里得到该对象,但是希望它在PaintEventArgs传递给您……如果没有,您的代码中还有其他设计缺陷)可能会更加宽容,但并非如此线程安全的。 You could add synchronization around the actual uses of the object, but those uses are the slow part. 您可以围绕对象的实际用途添加同步,但是这些用途是较慢的部分。 Serializing them will negate most of the benefit of concurrency in the code. 序列化它们将消除代码中并发的大部分好处。

Your question does not make clear whether your use of Parallel here was even an actual attempt to address some specific performance problem, never mind what that problem actually was. 您的问题并不清楚您是否在此处使用Parallel甚至是解决某些特定性能问题的实际尝试,也不要介意该问题实际上是什么。 There are numerous questions with answers on Stack Overflow that discuss various techniques for improving rendering performance in Windows Forms code. 关于Stack Overflow的答案有很多问题,讨论了用于改善Windows Forms代码中呈现性能的各种技术。

In general, most of these techniques involve reducing the total amount of work done by caching as much as possible. 通常,大多数这些技术都涉及通过尽可能多地缓存来减少完成的工作总量。 Based on the code you've shown, there are at least two things you might want to do: 根据显示的代码,您可能至少要做两件事:

  1. Cache the computations for the rectangles and colors. 缓存矩形和颜色的计算。 You can even do that part of the computation with Parallel , whenever the underlying parameters change. 每当基础参数发生更改时,您甚至可以使用Parallel进行计算的那部分。
  2. Draw everything into a Bitmap object. 将所有内容绘制到Bitmap对象中。 This will have to be done single-threaded, but a) it doesn't have to be done in the UI thread that owns your UI objects, and b) you (again) can do this just once, whenever the underlying parameters change. 这必须是单线程完成的,但是a)不必在拥有UI对象的UI线程中完成,并且b)只要基础参数发生更改,您(再次)只能执行一次。 Having drawn into a Bitmap , then you can just draw the Bitmap object when the Paint event occurs, instead of having to re-render everything from scratch. 绘制成Bitmap之后,您就可以在Paint事件发生时绘制Bitmap对象,而不必从头开始重新渲染所有内容。

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

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