【发布时间】:2012-02-23 18:18:51
【问题描述】:
我的应用程序在 BackgroundWorker 中加载了大量图像以保持可用。我的图像控件绑定到名为“ImageSource”的属性。如果为 null,则会在后台加载并再次引发。
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 中不可见,并且仍然会发生错误。据我了解,复制新文件时会发生错误,因为我的应用程序锁定了缓存文件。
-
为什么要设置 imageSource = null;和 RaisePropertyChanged("ImageSource"); ?你能不能只将用户指定的文件加载到 imageSource,RaisePropertyChanged("ImageSource")(它将使用 imageSource,因为它不为空),然后使用后台线程到 File.WriteAllBytes ?
-
感谢您的评论,但这会导致类似的例外情况。我现在有一个解决我这个房子问题的方法(见答案)。
标签: wpf multithreading image