Wpf 在后台加载图像而不锁定文件
我的应用程序在BackgroundWorker中加载大量图像以保持可用性。我的图像控件绑定到名为“ImageSource”的属性。如果为空,则在后台加载并再次引发Wpf 在后台加载图像而不锁定文件,wpf,multithreading,image,Wpf,Multithreading,Image,我的应用程序在BackgroundWorker中加载大量图像以保持可用性。我的图像控件绑定到名为“ImageSource”的属性。如果为空,则在后台加载并再次引发 public ImageSource ImageSource { get { if (imageSource != null) { return imageSource; }
public ImageSource ImageSource
{
get
{
if (imageSource != null)
{
return imageSource;
}
if (!backgroundImageLoadWorker.IsBusy)
{
backgroundImageLoadWorker.DoWork += new DoWorkEventHandler(bw_DoWork);
backgroundImageLoadWorker.RunWorkerCompleted +=
new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
backgroundImageLoadWorker.RunWorkerAsync();
}
return imageSource;
}
}
void bw_DoWork(object sender, DoWorkEventArgs e)
{
bitmap = new BitmapImage();
bitmap.BeginInit();
try
{
bitmap.CreateOptions = BitmapCreateOptions.DelayCreation;
bitmap.DecodePixelWidth = 300;
MemoryStream memoryStream = new MemoryStream();
byte[] fileContent = File.ReadAllBytes(imagePath);
memoryStream.Write(fileContent, 0, fileContent.Length);
memoryStream.Position = 0;
bitmap.StreamSource = memoryStream;
}
finally
{
bitmap.EndInit();
}
bitmap.Freeze();
e.Result = bitmap;
}
void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
BitmapSource bitmap = e.Result as BitmapSource;
if (bitmap != null)
{
Dispatcher.CurrentDispatcher.BeginInvoke(
(ThreadStart)delegate()
{
imageSource = bitmap;
RaisePropertyChanged("ImageSource");
}, DispatcherPriority.Normal);
}
}
到目前为止一切都很好,但我的用户可以更改有问题的图像。他们在OpenDialog中选择一个新图像,旧图像文件被新图像覆盖,并且再次引发ImageSource,从而再次加载具有相同文件名的新图像:
public string ImagePath
{
get { return imagePath; }
set
{
imagePath= value;
imageSource = null;
RaisePropertyChanged("ImageSource");
}
}
在某些系统上,覆盖旧文件会导致异常:
"a generic error occured in GDI+" and "The process cannot access the file..."
我尝试了很多方法,比如使用BitmapCreateOptions.IgnoreImageCache和BitmapCacheOption.OnLoad加载。这会在加载时引发异常:
Key cannot be null.
Parameter name: key
如果我在UI线程上没有BackgroundWorker的情况下尝试这一点,那么效果很好。我做错什么了吗?难道不可能在后台加载图像,同时保持文件的解锁状态吗?好吧,似乎上述所有方法都能奏效。我简化了这个问题的例子,但不知怎么的,我在路上把问题弄丢了
我在代码中看到的唯一区别是,图像本身的加载被委托给了一个特定的图像加载程序类,它以某种方式造成了问题。当我删除此依赖项时,错误消失。请发布您的“这将导致对ImageSource的新调用,该调用将再次加载具有相同文件名的新图像”。你为什么又装了。为什么不直接使用你拥有的图像并覆盖文件?@BalamBalam这实际上只是在设置新(或现有)文件路径后再次调用RaisePropertyChanged(“ImageSource”)。如果我不再次加载ImageSource,只复制文件,则更改在UI中不可见,错误仍然发生。据我所知,复制新文件时会发生错误,因为我的应用程序将文件锁定在缓存中;和RaisePropertyChanged(“ImageSource”)?您是否可以将用户指定的文件加载到imageSource、RaisePropertyChanged(“imageSource”)(因为它不为null,所以将使用imageSource),然后使用后台线程将其加载到file.WriteAllBytes?感谢您的评论,但这会导致类似的异常。我现在有了一个解决这个由房子造成的问题的办法(见答案)。