后台工作线程 e.结果导致调用线程无法访问错误
本文关键字:线程 访问 调用 错误 工作 结果 后台 | 更新日期: 2023-09-27 18:34:32
我已经阅读了很多与BackgroundWorker 和 DispatcherTimer 相关的 SO 问题,并了解您无法访问主线程以外的任何线程上的 UI 组件。
所以我有每 1/2 秒滴答一次的调度程序计时器。如您所料,我可以更新视图模型类和任何需要直接操作的 UI 元素,并且 UI 响应迅速。但是,我有一个基于UI上的值的计算,运行大约需要3秒。
我尝试只在调度程序计时器线程中进行计算,并锁定/阻止 UI,直到它完成。目前,我在调度程序计时器中有一个检查,然后触发后台工作线程关闭并进行计算。我使用 e.Arguments 来传递我的 3 秒计算过程所需的数据,以及 e.结果 对于我返回的已完成数据。
我已经检查了结果,没有生成任何错误。但是,当我将 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 thread上。
据我所知,就我访问 UI 组件的地点/时间而言,我已经做了所有正确的事情。虽然我想我在某处做错了什么。
**编辑:这是执行计算的代码的一部分
public static List<PathGeometry> BuildMap(List<PathGeometry> _geoList)
{
...
List<PathGeometry> retGeoList = new List<PathGeometry>();
retGeoList.Add(geoPath1);
retGeoList.Add(geoPath2);
...
return retGeoList;
}
该对象归创建它的 ThreadPool 线程所有。
如果你调用Freeze()
,它应该可以被其他线程使用。