从后台线程更新时,UI 会略微冻结

本文关键字:冻结 UI 后台 线程 更新 | 更新日期: 2023-09-27 18:36:48

我有一个带有 4 个 PictureBox 控件的 Winform,每个控件将包含一个不同的图像。该过程是:

引发一个事件 x,来自此事件的事件参数包含每个图像的文件名 (4),依此类推(文件存在等)。然后,我必须更新 UI。

通常我使用调用:

Invoke((ThreadStart)delegate()
{
    picBig.Image = new Bitmap(strImageBig);
    picLittle1.Image = new Bitmap(saLittle[0]);
    picLittle2.Image = new Bitmap(saLittle[1]);
    picLittle3.Image = new Bitmap(saLittle[2]);
});
// saLittle[] is a string array, contains, filenames: "image1.jpg"

但是当它执行时,表单会冻结一段时间,大约 500 毫秒,我知道这是一个很小的间隔,但它很明显,然后应用程序正常继续。

试图找出"UI冻结"的原因,然后,经过研究,我找到了BeginInvoke。现在我的代码如下所示:

BeginInvoke((MethodInvoker)delegate
{
    picBig.Image = new Bitmap(strImageBig);
    picLittle1.Image = new Bitmap(saLittle[0]);
    picLittle2.Image = new Bitmap(saLittle[1]);
    picLittle3.Image = new Bitmap(saLittle[2]);
});

这有点快。但 UI 仍然冻结了 200~300 毫秒。

在我读过的文章中,他们说 BeginInvoke 是比 Invoke 更好的方法。

代码工作正常,逻辑或其他任何东西都没有问题。我只想知道为什么会这样。我不想让这个疑问不清楚。该项目已经完成。希望这对其他人有用。

也许这不是正确的方法。我知道有很多方法可以从后台线程更新 UI,但是有没有另一种方法可以更快地更新?

或者,您认为图像加载是原因吗?有没有另一种方法可以更快地加载图像?

提前谢谢。

从后台线程更新时,UI 会略微冻结

这是因为您实际上是在 UI 线程上从磁盘加载图像,同时设置控件的内容。使用文件路径调用 Bitmap 构造函数将转到硬盘驱动器并将图像加载到内存中。

InvokeBeginInvoke 将在创建控件的线程上运行您提供的委托,该线程很可能是 UI 线程。

。但是有没有另一种方法可以更快地更新?

后台线程上加载图像,并在实际加载图像时调用图像并将其设置为控件。

                    var big = new Bitmap(strImageBig);
                    var little1 = new Bitmap(saLittle[0]);
                    var little2 = new Bitmap(saLittle[1]);
                    var little3 = new Bitmap(saLittle[2]);
                    Invoke((ThreadStart)delegate()
                    {
                        picBig.Image = big;
                        picLittle1.Image = little1;
                        picLittle2.Image = little2;
                        picLittle3.Image = little3;
                    });                    

但是当它执行时,表单会冻结一段时间,大约 500 毫秒,我知道这是一个很小的间隔,但它很明显,然后应用程序正常继续。

最终,UI 线程需要实际更新图像。 在 UI 线程上生成和更新图像时,这将导致(短暂)延迟。