Я сморщил изображение в потоке BackgroundWorker, и мне нужно обновить пользовательский интерфейс после того, как изображение будет обработано. Изображение, которое мне нужно обновить, существует в том же классе, что и DitherWorker. Как передать BitmapSource, чтобы отмеченная ошибка не возникала?
public void DitherWorker()
{
double scalebox = Double.Parse(myWindow.scaleBox.Text);
int slider = (int)myWindow.convolutionBiasSlider.Value;
BitmapSource final = null;
ditherobj output = new ditherobj(scalebox, originalImage, slider);//.Get_Halftone();
worker = new BackgroundWorker();
worker.WorkerSupportsCancellation = true;
worker.DoWork += delegate(object s, System.ComponentModel.DoWorkEventArgs args)
{
ditherobj dob = (ditherobj)args.Argument;
Binarize bn = new Binarize(dob.scalebox, dob.localbms, dob.slider);
BitmapSource bms = (BitmapSource)bn.Get_Halftone();
final = bms;
args.Result = new ditherobj(0,null,0,bms);
};
worker.RunWorkerCompleted += delegate(object s, RunWorkerCompletedEventArgs args)
{
ditherobj dob = (ditherobj)args.Result;
image1.Source = dob.localbms; //ERROR. The calling thread cannot access this object because another thread owns it
myWindow.Dispatcher.Invoke(DispatcherPriority.Normal, new ThreadStart(() =>
{
myWindow.activityBar.IsBusy = false;
}));
};
worker.RunWorkerAsync((ditherobj)output);
}
public class ditherobj
{
public double scalebox;
public BitmapSource localbms;
public BitmapImage localbmi;
public int slider;
public ditherobj(double scalebox, BitmapImage localbmi, int slider, BitmapSource bms = null)
{
this.scalebox = scalebox;
this.slider = slider;
if (bms == null)
{
BitmapImage test = localbmi.Clone();
localbms = (BitmapSource)test;
}
else
localbms = bms;
}
}
Проблема решена. Перед передачей BitmapSource должен быть заморожен в фоновом потоке. Вот окончательный кодированный код:
BackgroundWorker worker;
public void DitherWorker()
{
double scalebox = Double.Parse(myWindow.scaleBox.Text); //get values from UI for the job
int slider = (int)myWindow.convolutionBiasSlider.Value;
DitherSettings output = new DitherSettings(scalebox, originalImage, slider); //create holder object to be passed to BackgroundWorker
worker = new BackgroundWorker();
worker.DoWork += delegate(object s, System.ComponentModel.DoWorkEventArgs args)
{
DitherSettings ds = (DitherSettings)args.Argument; //cast argument as our holder object
Binarize bn = new Binarize(ds.scalebox, ds.localbms, ds.slider); //create object to do our work
BitmapSource bms = (BitmapSource)bn.Get_Halftone(); //do work
bms.Freeze(); //freeze resulting BitmapSource so it can be utilized elsewhere
args.Result = new DitherSettings(0,null,0,bms); //create new object with resulting BitmapSource
};
worker.RunWorkerCompleted += delegate(object s, RunWorkerCompletedEventArgs args)
{
DitherSettings ds = (DitherSettings)args.Result; //get object with our BitmapSource
if (image1.Dispatcher.CheckAccess())
this.image1.Source = ds.localbms; //update class image
myWindow.Dispatcher.Invoke(DispatcherPriority.Normal, new ThreadStart(() =>
{
myWindow.activityBar.IsBusy = false; //Update UI control
}));
};
worker.RunWorkerAsync((DitherSettings)output);
}
public class DitherSettings
{
public double scalebox;
public BitmapSource localbms;
public BitmapImage localbmi;
public int slider;
public DitherSettings(double scalebox, BitmapImage localbmi, int slider, BitmapSource bms = null)
{
this.scalebox = scalebox;
this.slider = slider;
if (bms == null)
localbms = (BitmapSource)localbmi;
else
localbms = bms;
}
}