后台线程更新时界面略有冻结。

4

我有一个Winform,其中包含4个PictureBox控件,每个控件都包含不同的图片。过程如下:

触发事件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]);
});

这种方法稍微快了一点。但是界面仍然会冻结200-300毫秒。

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

代码运行良好,逻辑或其他方面没有问题。我只是想知道为什么会出现这种情况。我不想让这个疑问不明朗。项目已经完成。希望对其他人有用。

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

或者,你认为图片加载是原因吗?有没有另一种更快速地加载图片的方法?

提前感谢您。

2个回答

4
这是因为在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;
                    });                    

0
但是当这个程序执行时,表单会冻结一小段时间,大约500毫秒,我知道这是一个很短的间隔,但是它是可以察觉到的,然后应用程序就会正常继续运行。最终,UI线程需要实际更新图像。当图像在UI线程上生成和更新时,这将导致(短暂的)延迟。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接