1

我已经阅读了很多与 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 列表时,我收到此错误:base {System.SystemException} = {“调用线程无法访问此对象,因为不同的线程拥有它。”}

在我使用 DrawUIMap 方法并尝试访问 MyClass.MapGeo 几何列表之前,我实际上并没有看到错误。此时我又回到了可以访问 UI 的 DispatcherTimer 线程。

据我所知,就访问 UI 组件的位置/时间而言,我已经完成了所有工作。虽然我认为我在某处做了一些可怕的错误。

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

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

1 回答 1

0

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

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

于 2013-10-09T16:21:01.010 回答