WPF和后台工作者问题

sim*_*mon 2 c# wpf multithreading

在我的程序中有一个BackgroundWorker类,它将图像预加载到BitmapImage对象.我需要将预加载的图像传递给主应用程序(WPF),然后将其复制到另一个BitmapImage对象.然而,当我尝试时,这似乎有效

imgViewer.Source = imgNext;  //imgNext is a main app copy of the preloaded image
Run Code Online (Sandbox Code Playgroud)

发生错误意味着该对象(imgNext)由另一个线程拥有并且无法使用.

任何想法如何摆脱它并使代码工作?

谢谢大家的回答!

事实上,我设法通过创建一个静态BitmapImage内部App类来解决这个问题.在使用它之前,我做到了

 App.iNext = null;
Run Code Online (Sandbox Code Playgroud)

然后我加载实际图像并冻结它,这样就可以从任何地方访问这个静态属性.当循环重复多次时,指定null可防止"对象冻结"错误.

当然,管理单个BGW实例,排队任务等方面还有很多工作要做.

(目前我正在使用在我的程序中定义的ImagesContainer类,它具有两个BitmapImage属性.我用它来接收来自backgroundworker的预加载图像.)

imgNext是MainWindow中定义的公共变量.(主线程)

 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);
Run Code Online (Sandbox Code Playgroud)

冻结bitmapimage仅对第一次背景加载有帮助(请参阅下面答案中的注释).当我第二次调用BackgroundWorker时,会发生一个错误,即对象被冻结且无法修改.有没有办法解冻它?

或者,有没有办法将数据从一个线程复制到另一个线程而不将属性复制到线程?



更新

谢谢大家的回答!

事实上,我设法通过创建一个静态BitmapImage内部App类来解决这个问题.在使用它之前,我做到了

 App.iNext = null;
Run Code Online (Sandbox Code Playgroud)

然后我加载实际图像并冻结它,这样就可以从任何地方访问这个静态属性.当循环重复多次时,分配null可防止错误.

当然,管理单个BGW实例,排队任务等方面还有很多工作要做.

但这些努力值得结果 - 我的性能提升了+ 125%!谢谢大家!

Ken*_*art 6

BitmapImageFreezable这样你Freeze()加载后就可以了.这将允许从任何线程访问.