我已经阅读了很多与 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;
}