我有一个WPF控件正在我的应用程序的主线程中处理,渲染和显示。控件将数千个数据点上传到名为“Layer”的对象中。以下是对象/类层次结构的粗略描述:
public class WPFControl{
private List<Layer> myLayers;
public List<Layer> MyLayers{
get{ return myLayer;}
}
...
}
public class Layer{
private List<DataPoint> myDataPoints;
public List<DataPoint> MyDataPoints{
get{ return myDataPoints;}
}
...
}
public class DataPoint{
....
}
由于这个“Layer”对象的创建过程需要一些时间,因为它必须读取和上传数千个DataPoint,因此我在另一个线程中创建该层对象。这很好用,很好地返回Layer对象。问题是,当我尝试将其添加到WPF控件时,显示如下:
myWpfControl.MyLayers.Add(layerCreatedInOtherThread);
WPF控件触发此错误:
The calling thread cannot access this object because a different thread owns it
我想,好吧,我可以像这样使用调度员:
myWpfControl.Dispatcher.Invoke((Action)
(()=>{
myWpfControl.MyLayers.Add(layerCreatedInOtherThread);
})
);
但我一直得到同样的错误。我有什么想法可以解决这个问题吗?
答案 0 :(得分:0)
使用BackgroundWorker
,您可以在另一个线程上运行任务,然后在完成后可以访问UI线程中的结果。
private System.ComponentModel.BackgroundWorker bgWorker;
bgWorker.DoWork += new DoWorkEventHandler(bgWorker_DoWork);
bgWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bgWorker_RunWorkerCompleted);
//Start the work
bgWorker.RunWorkerAsync(null) //you can send an argument instead of null
做好工作
private void backgroundWorker1_DoWork(object sender,
DoWorkEventArgs e)
{
// Get the BackgroundWorker that raised this event.
BackgroundWorker worker = sender as BackgroundWorker;
// Assign the result of the computation
// to the Result property of the DoWorkEventArgs
// object. This is will be available to the
// RunWorkerCompleted eventhandler.
e.Result = CreateLayerInOtherThread(); //if you sent an arg instead of null it as availalbe in e.Argument and can be cast from object.
}
完成后获得结果。这在UI线程上运行,因此您可以更新它。
private void bgWorker_RunWorkerCompleted(
object sender, RunWorkerCompletedEventArgs e)
{
// First, handle the case where an exception was thrown.
if (e.Error != null)
{
MessageBox.Show(e.Error.Message);
}
else if (e.Cancelled)
{
// Next, handle the case where the user canceled
// the operation.
// Note that due to a race condition in
// the DoWork event handler, the Cancelled
// flag may not have been set, even though
// CancelAsync was called.
}
else
{
// Finally, handle the case where the operation
// succeeded.
Layer myLayer = (Layer)e.Result;
myWpfControl.MyLayers.Add(myLayer);
}
}