C# Windows窗体并行绘图

C# Windows窗体并行绘图,c#,winforms,graphics,parallel-processing,runtime-error,C#,Winforms,Graphics,Parallel Processing,Runtime Error,是否可以使用并行.For循环在面板上绘制?我有一个多维的double数组,double[][]plants,我想并行绘制列,其中数组中的每个条目在面板的网格中绘制为矩形 在使用grapahics.FillRectangle()的行中,我在尝试时不断遇到以下错误: System.Drawing.dll中发生“System.InvalidOperationException”类型的异常,但未在用户代码中处理 其他信息:对象当前正在其他地方使用 以下是我正在使用的代码: Parallel.Fo

是否可以使用
并行.For
循环在面板上绘制?我有一个多维的double数组,
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(0,simWidth,i=>
{
植物颜色;
矩形F plantRectangle=新矩形();
SolidBrush plantBrush=新的SolidBrush(颜色为黑色);
对于(int j=0;j
我认为现在的情况是图形对象不能同时处理多个调用。这有什么办法吗?我尝试在每次并行调用中创建图形对象的本地引用,但没有成功

可以用平行的For循环在面板上画图吗

不,无论如何那都不是真的有用

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

GDI+对象,比如你的
图形
对象(你没有说你从哪里得到了那个对象,但人们希望它是在
PaintEventArgs
中传递给你的……如果不是,你的代码中还有其他设计缺陷)可以原谅,但不是线程安全的。您可以围绕对象的实际使用添加同步,但这些使用是缓慢的部分。序列化它们将否定代码中并发的大部分好处

您的问题没有明确说明您在这里使用的
并行
是否是为了解决某些特定性能问题的实际尝试,更不用说该问题实际上是什么。有许多关于堆栈溢出的问题和答案,这些问题讨论了在Windows窗体代码中提高渲染性能的各种技术

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

  • 缓存矩形和颜色的计算。只要底层参数发生变化,您甚至可以使用
    Parallel
    进行这部分计算
  • 将所有内容绘制到
    位图
    对象中。这必须通过单线程完成,但a)不必在拥有UI对象的UI线程中完成,b)只要底层参数发生变化,您(再次)就可以只执行一次。绘制到
    位图
    后,当
    绘制
    事件发生时,您可以只绘制
    位图
    对象,而不必从头开始重新渲染所有内容

  • graphics
    来自
    PaintEventArgs e
    e.graphics
    。我想让它并行,因为它本质上“渲染”了我的模拟。缓存和使用
    位图
    听起来不错,谢谢!