在我的程序中,有一个BackgroundWorker类,可将图像预加载到BitmapImage对象。我需要将该预加载的图像传递到主应用程序(WPF),然后将其复制到另一个BitmapImage对象。这似乎在工作,但是,当我尝试
imgViewer.Source = imgNext; //imgNext is a main app copy of the preloaded image
发生错误,意味着该对象(imgNext)由另一个线程拥有,并且无法使用。
有什么想法如何摆脱它并使代码正常工作吗?
谢谢大家的回答!
实际上,我设法通过在
BitmapImage
类内创建一个静态App
来解决此问题。在使用它之前,我会
App.iNext = null;
然后,我加载实际图像并将其冻结,以便可以从任何地方访问此静态属性。当循环重复多次时,为null分配可防止“对象被冻结”错误。
当然,管理单个BGW实例,排队任务等还有很多工作。
(当前,我正在使用在程序中还定义的ImagesContainer类,该类具有两个BitmapImage属性。我用它来接收来自backgroundworker的预加载图像。)
imgNext是在MainWindow中定义的公共(public)变量。 (主线程)
void bwImgLoader_DoWork(object sender, DoWorkEventArgs e)
{
backgrLoadNextPrevList list = e.Argument as backgrLoadNextPrevList;
ImagesContainer result = new ImagesContainer();
if (list.HasNextPath) result.imgPrev = PrepareImage(list.NextPath);
if (list.HasPrevPath) result.imgNext = PrepareImage(list.PrevPath);
e.Result = result;
}
void bwImgLoader_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
ImagesContainer result = e.Result as ImagesContainer;
if (result.imgNext != null)
{
setNextDelegate s = new setNextDelegate(setNext);
object[] t = { result.imgNext };
imgNext.Dispatcher.Invoke(s, t);
}
// do not take into account this line, just ignore it.
//if (result.imgPrev != null) imgPrev = result.imgPrev;
}
public void setNext(BitmapImage b)
{
imgNext = b;
}
public delegate void setNextDelegate(BitmapImage b);
冻结位图图像仅对第一次后台加载有所帮助(请参见下面答案中的注释)。当我第二次调用BackgroundWorker时,发生了一个错误,该对象被冻结并且无法修改。有解冻的方法吗?
或者,是否有任何方法可以将数据从一个线程复制到另一个线程而无需将属性复制到线程?
更新了
谢谢大家的回答!
实际上,我设法通过在
BitmapImage
类内创建一个静态App
来解决此问题。在使用它之前,我会
App.iNext = null;
然后,我加载实际图像并将其冻结,以便可以从任何地方访问此静态属性。当循环重复多次时,为null分配值可防止错误。
当然,管理单个BGW实例,排队任务等还有很多工作。
但是这些努力是值得的-我获得了+ 125%的性能!!!谢谢大家!
最佳答案
BitmapImage
是Freezable
,因此您可以在加载后对其进行Freeze()
。这将允许从任何线程进行访问。
关于c# - WPF和背景 worker 问题,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/4617292/