【问题标题】:UI slightly freezes when update from background thread从后台线程更新时,UI 略微冻结
【发布时间】:2023-03-28 07:10:01
【问题描述】:

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

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

我通常使用 Invoke:

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~300ms。

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

代码运行正常,逻辑或其他方面没有问题。我只是想知道为什么会这样。我不想让这个疑问不清楚。该项目已经完成。希望这对其他人有用。

也许这不是正确的方法。我知道有很多方法可以从后台线程更新 UI,但是还有其他方法可以让更新更快吗?

或者,您认为是图像加载的原因吗?还有其他方法可以更快地加载图像吗?

提前致谢。

【问题讨论】:

    标签: c# multithreading user-interface delegates


    【解决方案1】:

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

    Invoke 和BeginInvoke 将在创建控件的线程上运行您提供的委托,该线程很可能是 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;
                        });                    
    

    【讨论】:

      【解决方案2】:

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-04-24
        • 1970-01-01
        • 1970-01-01
        • 2017-09-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多