尝试绘制多线程矩形

本文关键字:多线程 绘制 | 更新日期: 2023-09-27 17:57:19

我正在尝试在表单上绘制大约 3600 个点,使用一个线程非常慢,所以我决定要使用 4 个线程。

在我的代码中,我将 3600 点划分为 4 个线程,他们应该绘制它。 但是由于某种原因,ArgumentOutOfRangeException被抛出。我尝试调试我的代码,但找不到错误。

这是代码:

(忽略类_3DPoint,它只是一个具有 x,y,z 值的点。 当我绘制它们时,我只使用 x,y 值。

绘制点的代码:

    public Graphics g; //g = this.CreateGraphics() in form1.Load()
    public void drawrectangle(_3DPoint)
        float xCord = float.Parse(p.x.ToString());
        float yCord = float.Parse(p.y.ToString());
        Brush b = new SolidBrush(Color.White);
        xCord = lsize * xCord + center.X;
        yCord = lsize * yCord + 10 + center.Y;
        g.FillRectangle(b, xCord, yCord, 2, 2);
    }

lsize,center只是用于按照我想要的点对齐的变量。

所有多线程操作代码:

    public List<_3DPoint[]> multiThreadsdata = new List<_3DPoint[]>();
    public void handlemultithread(_3DPoint[] P)
    {
        g.Clear(Color.Black);
        for (int i = 0; i < multiThreads.Length; i++)
        {
            multiThreadsdata.Add(new _3DPoint[P.Length / multiThreads.Length]);
        }
        for (int i = 0; i < multiThreads.Length; i++)
        {
            for (int j = (P.Length / multiThreads.Length) * (i); j < (P.Length / multiThreads.Length) * (i + 1); j++)
            {
                multiThreadsdata[i][j - ((P.Length / multiThreads.Length) * i)] = new _3DPoint(P[j]);
            }
        }
        for (int i = 0; i < multiThreads.Length; i++)
        {
            multiThreads[i] = new Thread(() => drawPoints(multiThreadsdata[i]));
            multiThreads[i].Start();
        }
    }
    delegate void SetCallBackPoint(_3DPoint location);
    public void drawPoints(_3DPoint[] locations)
    {
        for (int i = 0; i < locations.Length; i++)
        {
            if (this.InvokeRequired)
            {
                SetCallBackPoint e = new SetCallBackPoint(drawrectangle);
                this.Invoke(e, new object[] { locations[i] });
            }
            else
            {
                drawrectangle(locations[i]);
            }
        }
    }

P 是一个包含所有 3600 个点的_3DPoint数组。

mutliThreads 是一个包含 4 个线程的线程 []。

我在这个for循环的第三行handlemultithread方法中得到异常:

for (int i = 0; i < multiThreads.Length; i++)
        {
            multiThreads[i] = new Thread(() => drawPoints(multiThreadsdata[i])); // <- here.
            multiThreads[i].Start();
        }

我不知道问题是什么,我的猜测是多线程存在一些问题,因为我只是多线程的初学者。

谢谢一堆。

尝试绘制多线程矩形

当您应用注释中的建议时,完全可以在表单上快速绘制 3600 个矩形。

如果这还不够您足够的时间,您可以考虑在单个后台线程上创建 Images,将它们存储在某种缓冲区中,直到需要将它们绘制在表单Paint事件的Graphics对象上。只有当您可以预先知道需要在下一帧上绘制什么时,这才是可行的。

此示例使用简单的后台辅助角色用图像填充ConcurrentQueue。代码中的注释解释了正在发生的事情。

public partial class Form1 : Form
{
    static ConcurrentQueue<Image>  buffer = new ConcurrentQueue<Image>();
    static Random r = new Random();
    public Form1()
    {
        InitializeComponent();
        backgroundWorker1.RunWorkerAsync();
        // this is already a great performance win ...
        DoubleBuffered = true;
    }
    private void Form1_Paint(object sender, PaintEventArgs e)
    {
        Image img =null;
        // get from buffer ..
        if (!buffer.TryDequeue(out img))
        {
            // nothing available
            // direct random
            for (var x = 0; x < e.ClipRectangle.Width; x++)
            {
                for (var y = 0; y < e.ClipRectangle.Height; y++)
                {
                    using (var pen = new Pen(new SolidBrush(Color.FromArgb(r.Next(255), r.Next(255), r.Next(255)))))
                    {
                        e.Graphics.DrawRectangle(pen, x, y, 1, 1);
                    }
                }
            }
        }
        else
        {
            // otherwise Draw the prepared image
            e.Graphics.DrawImage(img,0,0);
            Trace.WriteLine(buffer.Count);
            img.Dispose();
        }
    }
    private void button1_Click(object sender, EventArgs e)
    {
        // force a repaint of the Form
        Invalidate();
    }
    private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    {
        // as long as the form is not disposed
        while (!IsDisposed)
        {
            // we keep 60 images in memory
            if (buffer.Count < 60)
            {
                // bitmap
                var bmp = new Bitmap(this.Width, this.Height);
                var img = Graphics.FromImage(bmp);
                // draw
                for (int i = 0; i < 3600; i++)
                {
                    using (var pen = new Pen(new SolidBrush(Color.FromArgb(r.Next(255), r.Next(255), r.Next(255)))))
                    {
                        img.DrawRectangle(pen, r.Next(Width),r.Next(Height), r.Next(Width), r.Next(Height));
                    }
                }
                // store the drawing in the buffer
                buffer.Enqueue(bmp);
            }
            else
            {
                // simple and naive way to give other threads a bit of room
                Thread.Sleep(0);
            }
        }
    }
}

请记住,当您有一个 CPU 密集型进程时,添加更多线程不会神奇地使您的方法运行得更快。你甚至可能让情况变得更糟:更多的线程在 CPU 上竞争时间。