WPF 的Image 控件 设置 Image.Source 的数据源,可能存在跨线程调用的问题。
相信很多WPF 的开发,应该都很多用到 Image 这个控件来显示图片。这个图片的来源可以来自各种各样的方式获取到。
我们的组内白板、批注的扫码的功能也用到这个去生成二维码,生成后,二维码显示不出来,由于触发到了全局捕获,界面又没有崩溃,遇到了好几个坑,记录一下。
开始看代码:
private async void MainWindow_Loaded(object sender, RoutedEventArgs e) { ImageSource imageSource = null; //用来模拟时间回调后,去获取图片资源 Task.Run(() => { imageSource = BitmapImageToBitmap(); }); await Task.Delay(2000); MyImage.Source = imageSource; } public static BitmapImage BitmapImageToBitmap() { BitmapImage bitmapImage = new BitmapImage(new Uri(@"C:\Users\a\Desktop\祁厅长壁纸.png", UriKind.RelativeOrAbsolute)); return bitmapImage; }
我们在工作线程上去获取ImageSource (模拟事件回调),然后在Loaded 事件中给 Image控件的Source 赋值。
其实细看一下ImageSource 的定义,是继承了 Animatable,而Animatable继承了Freezable,Animatable继承了Freezable,Freezable继承了DependencyObject
这也就是说,ImageSource 的创建和使用必须是同一个线程下的,不然就会存在以上的异常报错
Freezable.Freeze Method (System.Windows) | Microsoft Learn
解决方法:
BitmapImage 在获取图片的时候,提供了Freenze()的方法
public static BitmapImage BitmapImageToBitmap() { BitmapImage bitmapImage = new BitmapImage(new Uri(@"C:\Users\a\Desktop\祁厅长壁纸.png", UriKind.RelativeOrAbsolute)); if (bitmapImage.CanFreeze) { bitmapImage.Freeze(); } return bitmapImage; }
加上就可以正常显示了,效果如下: