问题描述
使用WPF在C#中异步加载BitmapImage的最佳方法是什么?
What's the best way to asynchronously load an BitmapImage in C# using WPF?
推荐答案
我只是调查这个问题,不得不投入两分钱,尽管最初的帖子过了几年(以防其他人找寻)我正在调查的同一件事).
I was just looking into this and had to throw in my two cents, though a few years after the original post (just in case any one else comes looking for this same thing I was looking into).
我有一个图片控件,需要使用 Stream 将其图片加载到后台,然后显示.
I have an Image control that needs to have it's image loaded in the background using a Stream, and then displayed.
我一直遇到的问题是 BitmapSource ,它的 Stream 源和 Image 控件必须位于同一位置线程.
The problem that I kept running into is that the BitmapSource, it's Stream source and the Image control all had to be on the same thread.
在这种情况下,使用Binding并将其设置为IsAsynch = true将引发跨线程异常.
In this case, using a Binding and setting it's IsAsynch = true will throw a cross thread exception.
BackgroundWorker非常适合WinForms,您可以在WPF中使用它,但是我宁愿避免在WPF中使用WinForm程序集(不建议对项目进行膨胀,这也是一个很好的经验法则).在这种情况下,这也应该引发无效的交叉引用异常,但是我没有对其进行测试.
A BackgroundWorker is great for WinForms, and you can use this in WPF, but I prefer to avoid using the WinForm assemblies in WPF (bloating of a project is not recommended, and it's a good rule of thumb too). This should throw an invalid cross reference exception in this case too, but I didn't test it.
结果证明,一行代码可以完成以下任何一项工作:
Turns out that one line of code will make any of these work:
//Create the image control
Image img = new Image {HorizontalAlignment = System.Windows.HorizontalAlignment.Stretch, VerticalAlignment = System.Windows.VerticalAlignment.Stretch};
//Create a seperate thread to load the image
ThreadStart thread = delegate
{
//Load the image in a seperate thread
BitmapImage bmpImage = new BitmapImage();
MemoryStream ms = new MemoryStream();
//A custom class that reads the bytes of off the HD and shoves them into the MemoryStream. You could just replace the MemoryStream with something like this: FileStream fs = File.Open(@"C:\ImageFileName.jpg", FileMode.Open);
MediaCoder.MediaDecoder.DecodeMediaWithStream(ImageItem, true, ms);
bmpImage.BeginInit();
bmpImage.StreamSource = ms;
bmpImage.EndInit();
//**THIS LINE locks the BitmapImage so that it can be transported across threads!!
bmpImage.Freeze();
//Call the UI thread using the Dispatcher to update the Image control
Dispatcher.BeginInvoke(new ThreadStart(delegate
{
img.Source = bmpImage;
img.Unloaded += delegate
{
ms.Close();
ms.Dispose();
};
grdImageContainer.Children.Add(img);
}));
};
//Start previously mentioned thread...
new Thread(thread).Start();
这篇关于使用WPF在C#中异步加载BitmapImage的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!