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.