这几天我一直在解决backgroundWorker的问题。我查看了MSDN上的论坛和文献,但仍然没有找到答案,所以现在想请教聪明的您。
简而言之,我有一个自定义用户控件,包含一个ScrollViewer内的WrapPanel。WrapPanel包含一些元素,当它们滚动到视图中时会通知这些元素。然后,元素应该加载并显示图像,而这就是问题所在。为了不锁定GUI线程,我在BackgroundWorker中加载图像,但是GUI仍然会停顿。这是表示WrapPanel中包含元素的类的代码:
简而言之,我有一个自定义用户控件,包含一个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并非罪魁祸首。