BackgroundWorker e.Result导致调用线程无法访问错误

时间:2013-10-09 16:18:03

标签: c# wpf backgroundworker dispatchertimer

我已经阅读了很多与BackgroundWorker和DispatcherTimer相关的SO问题,并了解您无法访问主线程以外的任何线程上的UI组件。

所以我有DispatcherTimer每1/2秒滴答一次。正如您所料,我可以更新视图模型类和任何需要直接操作的UI元素,并且UI非常敏感。但是我根据UI上的值进行计算,运行大约需要3秒。

我尝试在DispatcherTimer线程中进行调用,并锁定/阻止UI直到完成。目前我在DispatcherTimer中检查然后触发BackgroundWorker线程以进行计算。我使用e.Arguments将我需要的数据传递给我的3秒计算过程,并使用e.Result获取我收到的已完成数据。

我检查了结果,没有生成错误。然而,当我将e.Result投回到我的班级时,e.Result无法正确评估。当我来使用类属性时,我基本上得到了“调用线程无法访问错误”。

...
timerBackgroundLoop = new DispatcherTimer(DispatcherPriority.Background);
timerBackgroundLoop.Interval = TimeSpan.FromMilliseconds(500);
timerBackgroundLoop.Tick += new EventHandler(Timer_Tick);
timerBackgroundLoop.Start();
...

private void Timer_Tick(object sender, EventArgs e)
{
    if (MyClass.NeedToRebuildBuildMap)
    {
        MyClass.NeedToRebuildBuildMap = false; //stop next timer tick from getting here
        threadDrawMap = new BackgroundWorker();
        threadDrawMap.WorkerReportsProgress = false;
        threadDrawMap.WorkerSupportsCancellation = false;
        threadDrawMap.DoWork += new DoWorkEventHandler(threadDrawMap_DoWork);
        threadDrawMap.RunWorkerCompleted += new RunWorkerCompletedEventHandler(threadDrawMap_Completed);
        threadDrawMap.RunWorkerAsync(myClass.MapData);
    }
    ...
}

private void threadDrawMap_DoWork(object sender, DoWorkEventArgs e)
{
    MyClass.MapData _mapData = (MyClass.MapData)e.Argument;                        
    e.Result  = BuildMap(_mapData);
}

private void threadDrawMap_Completed(object sender, RunWorkerCompletedEventArgs e)
{
    MyClass.MapGeo = (List<PathGeometry>)e.Result;
    DrawUIMap(MyClass.MapGeo); //draws the map on the UI into a grid
}

当我在“threadDrawMap_Completed”中设置一个中断并评估PathGeometry的List时,我得到这个错误:base {System.SystemException} = {“调用线程无法访问此对象,因为另一个线程拥有它。”}

直到我进入DrawUIMap方法并尝试访问MyClass.MapGeo几何列表时,我才真正看到错误。此时我回到了DispatcherTimer线程,该线程可以访问UI。

据我所知,我已经完成了所有操作,只要我访问UI组件的位置。虽然我认为我在某处做了一些可怕的错误。

**编辑: 这是执行计算的代码的一部分

public static List<PathGeometry> BuildMap(List<PathGeometry> _geoList)
{
    ...
    List<PathGeometry> retGeoList = new List<PathGeometry>();
    retGeoList.Add(geoPath1);        
    retGeoList.Add(geoPath2);
    ...
    return retGeoList;
}

1 个答案:

答案 0 :(得分:0)

该对象由创建它的ThreadPool线程拥有。

如果你致电Freeze(),它应该可以被其他线程使用。