在BackgroundWorker中加载图像

6
这几天我一直在解决backgroundWorker的问题。我查看了MSDN上的论坛和文献,但仍然没有找到答案,所以现在想请教聪明的您。
简而言之,我有一个自定义用户控件,包含一个ScrollViewer内的WrapPanel。WrapPanel包含一些元素,当它们滚动到视图中时会通知这些元素。然后,元素应该加载并显示图像,而这就是问题所在。为了不锁定GUI线程,我在BackgroundWorker中加载图像,但是GUI仍然会停顿。这是表示WrapPanel中包含元素的类的代码:
class PictureThumbnail : INotifyingWrapPanelElement
{
    private string path;
    private Grid grid = null;

    private BackgroundWorker thumbnailBackgroundCreator = new BackgroundWorker();
    private delegate void GUIDelegate();
    private Image thumbnailImage = null;

    public PictureThumbnail(String path)
    {
        this.path = path;
        visible = false;
        thumbnailBackgroundCreator.DoWork += new DoWorkEventHandler(thumbnailBackgroundCreator_DoWork);

    }

    void thumbnailBackgroundCreator_DoWork(object sender, DoWorkEventArgs e)
    {
        BitmapImage bi = LoadThumbnail();
        bi.Freeze(); //If i dont freeze bi then i wont be able to access 

        GUIDelegate UpdateProgressBar = delegate
        {
            //If this line is commented out the GUI does not stall. So it is not the actual loading of the BitmapImage that makes the GUI stall.
            thumbnailImage.Source = bi;
        };
        grid.Dispatcher.BeginInvoke(UpdateProgressBar);
    }


    public void OnVisibilityGained(Dispatcher dispatcher)
    {
        visible = true;
        thumbnailImage = new Image();
        thumbnailImage.Width = 75;
        thumbnailImage.Height = 75;

        //I tried setting the thumbnailImage.Source to some static BitmapImage here, and that does not make the GUI stall. So it is only when it is done through the GUIDelegate for some reason.
        grid.Children.Add(thumbnailImage);
        thumbnailBackgroundCreator.RunWorkerAsync();
    }



    private BitmapImage LoadThumbnail()
    {
        BitmapImage bitmapImage = new BitmapImage();

        // BitmapImage.UriSource must be in a BeginInit/EndInit block
        bitmapImage.BeginInit();
        bitmapImage.UriSource = new Uri(path);
        bitmapImage.DecodePixelWidth = 75;
        bitmapImage.DecodePixelHeight = 75;
        bitmapImage.EndInit();

        return bitmapImage;
    }
}

我已经在代码中添加了一些注释,解释了我尝试过的一些东西以及我的想法。但我会在这里再次写出来。如果我只是在backgroundWorker中加载BitmapImage,但没有将其应用为thumbnailImage的源,则GUI不会停顿(但显然不会显示任何图像)。此外,如果我在OnVisibilityGained方法(因此在GUI线程中)中将thumbnailImage的源设置为预加载的静态BitmapImage之一,则GUI不会停顿,因此实际设置Image.Source并非罪魁祸首。


可能是加载图像停止问题的重复。 - Jason Down
它会停顿,因为ThumbnailImage是从你的线程中更新的。我建议如果你有一个updateImage(BitmapImage i)方法,如果你使用bi变量调用它,它就不会再停顿了。 - BugFinder
1
@Jason,那个答案详细说明了解决方案是使用BackgroundWorker,而这个问题则详细说明了使用BackgroundWorker时遇到的问题。显然,对于BackgroundWorker的问题,答案不能是使用BackgroundWorker。 - Peter Ritchie
2
@PeterRitchie:是的,你说得对。Lajja Thaker说这个问题几天前就被问过了,所以我想我会以正确的方式链接到问题(防止重复),而不仅仅是在答案中链接到问题。不幸的是,我被其他事情分心了,当我回来时,我只是链接了问题而没有阅读它(假设会让你和我都成为傻瓜...在这种情况下是我)。如果我可以撤回关闭投票,我会的。让我们只说下次在盲目地尝试帮助之前,我一定会确保实际阅读问题。 - Jason Down
1个回答

1
你应该利用BackgroundWorker的报告功能,它让你直接访问表单控件而无需调用。

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