Loading Images in BackgroundWorker
Asked Answered
J

1

6

I have been dealing with a problem with a backgroundWorker these last couple of days. I have been looking through forums and documentation on MSDN but still haven't found the answer so now I want to ask you clever people.

Long story short, I have a custom user control consisting of a WrapPanel inside a ScrollViewer. The WrapPanel contains some elements that are notified when they are scrolled into view. The elements are then supposed to load and display an image, and this is where the problem comes in. In order to not lock the gui thread i load the images in a BackgroundWorker, but the GUI stalls anyways. This is the code for the class that represents the elements contained in the 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;
    }
}

I have added some comments in the code explaining some stuff I tried and what leads I have. But I'll write it again here. If I just load the BitmapImage in the backgroundWorker, but don't apply it as the Source of the thumbnailImage the GUI doesn't stall (but no image is displayed obviously). Also if I set the Source of the thumbnailImage to some preloaded static BitmapImage in the OnVisibilityGained method (So in the GUI thread), then the GUI wont stall, so it is not the actual setting of the Image.Source that's the culprit.

Janerich answered 25/9, 2012 at 13:4 Comment(4)
possible duplicate of Loading image stops issueTiflis
It stalls because ThumbnailImage is updated from your thread. Id suggest if you had an updateImage(BitmapImage i), if you invoked that with the bi variable, it would cease to stall.Soares
@Jason, that answer details that the solution is to use BackgroundWorker, this question is detailing problems using BackgroundWorker. Clearly the answer to problems with BackgroundWorker can't be to use BackgroundWorker.Auctorial
@PeterRitchie: Yes you are right. Lajja Thaker said this question was asked a few days ago so I figured I'd link to the question the proper way (prevent duplicates) rather than just link to the question in an answer. Unfortunately I got pulled away on something else and when I came back I just linked the question without reading it (assuming makes an ass of you and me... well me in this case). If I could take back the close vote I would. Let's just say I'll be sure to actually read the question before I blindly try to help next time.Tiflis
G
1

You should make use of the reporting feature of the backgroundworker which lets you directly access the controls of your form without invoking.

Giule answered 28/8, 2013 at 6:2 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.