C# 在多线程中将面板保存为图像

C# Saving Panel as image at Multithread

我在使用 UI 线程将面板保存为图像时没有任何问题,但是当我将此面板保存在 UI 线程以外的另一个线程时,我只有一个黑色矩形:

using (Bitmap bmp = new Bitmap(panel1.Width, panel1.Height, System.Drawing.Imaging.PixelFormat.Format24bppRgb))
        {
            if (panel1.InvokeRequired)
            {
                panel1.BeginInvoke((MethodInvoker)delegate ()
                {
                    panel1.DrawToBitmap(bmp, new System.Drawing.Rectangle(Point.Empty, bmp.Size));

                });
                Bitmap bb = bmp.Clone(new System.Drawing.Rectangle(0, 0, 1016, 648), PixelFormat.Format24bppRgb);
                bb.Save(@"C:\sample.bmp", ImageFormat.Bmp);
            }
            else
            {
              panel1.DrawToBitmap(bmp, new System.Drawing.Rectangle(Point.Empty, bmp.Size));
              Bitmap bb = bmp.Clone(new System.Drawing.Rectangle(0, 0, 1016, 648), PixelFormat.Format24bppRgb);
              bb.Save(@"C:\sample.bmp", ImageFormat.Bmp);
            }

        }

这个问题与锁定机制有关?或者我该如何解决这个问题?

提前致谢。

通用答案(有解释):

BeginInvoke是发送消息'this function should be executed in different thread'然后直接离开在当前线程继续执行的函数。

该函数稍后执行,当目标线程有 'free time' (处理之前发布的消息).

当你需要函数的结果时,使用InvokeInvoke 函数是 'slower',或者更确切地说,它会阻塞当前线程,直到执行的函数完成。 (我最近真的在 C# 中测试过这个,但有可能 Invoke 函数被优先考虑;例如,当你调用 BeginInvoke 并在它之后直接调用 Invoke 到同一个线程,Invoke 中的函数可能会在 BeginInvoke 中的函数之前执行。)

如果您需要在处理下一条指令之前执行该函数,请使用此选项(当您需要调用函数的结果时)

简单(tl;dr): 当你需要只需要设置一个值时(例如设置编辑框文本),使用BeginInvoke,但是当你需要结果时(例如从编辑框获取文本)总是使用Invoke

在您的情况下,您需要结果 (要绘制的位图) 因此您需要等待函数结束。 (还有其他可能的选择,但在这种情况下,简单的方法是更好的方法。)