gpt4 book ai didi

c# - 从 BackgroundWorker 返回一个对象

转载 作者:行者123 更新时间:2023-11-30 22:36:22 26 4
gpt4 key购买 nike

我在 BackgroundWorker 线程中对图像进行抖动处理,需要在图像处理完成后更新 UI。我需要更新的图像与 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;
}
}

最佳答案

当您仍在后台线程中时,调用 BitmapSource 上的 Freeze() 函数。

这使得对象不可变,因此可以在主线程上使用。

Learn here more about freezable wpf objects.该页面讨论了 Freezable 的许多其他方面,但它也明确指出:“卡住的 Freezable 也可以跨线程共享,...”。如果您问我,这种内置于 WPF 中以在后台线程上构建 GUI 元素(例如位图)的功能是 #1 未被充分宣传的 WPF 功能。

关于c# - 从 BackgroundWorker 返回一个对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7045707/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com