无法从另一个线程访问对象

3
我知道这个问题在其他问题中已经讨论过了,但是我正在苦恼——显然我错过了一些明显的东西。我会尝试为您提供一些背景信息……
我有一个UI线程,它冻结了,所以我创建了一个后台工作程序来处理所有繁重的处理任务,以保持我的UI交互性。
我需要为一些弧线/路径生成坐标,然后将其绘制在画布上。后台工作程序处理并运行其完成工作的方法,在其中将PathGeometry与一些其他数据存储在列表中。然后,我从我的后台工作程序中调用了一个update()方法,在UI线程中使用我传递给后台工作程序的对象。
我的问题是,当我开始在UI线程中构建Path对象(无法在后台工作程序线程中构建它们)时,我无法访问PathGeometries。我的对象是一个CommunicationArc,它包含PathGeometry、不透明度、颜色等信息。
The calling thread cannot access this object because a different thread owns it.

我可以访问对象的其他部分,但是无法访问PathGeometry,我不知道为什么。后台工作程序肯定已经完成,因为workcomplete方法已经运行并且所有的弧都存储在我的列表中。我只想在UI线程中读取这些弧,稍微处理一下,然后继续绘制它们。

我尝试使用来自我的UI线程的Dispatcher:

arc.pathGeometry.Dispatcher.BeginInvoke((Action)(() =>
            {
                MessageBox.Show(arc.pathGeometry.ToString());
            }));

但我不确定我所做的是否正确,各种调用Dispatcher的方法要么没有任何效果,要么会锁定BeginInvoke()上的所有内容。

任何帮助都将不胜感激,我感觉自己正在打转!


在使用UI线程之前,尝试在后台线程上调用Freeze,以冻结您的PathGeometry对象。 - Clemens
2个回答

3

您需要直接在UI线程上创建和操作几何对象。任何您执行的线程处理都不能直接访问几何对象,它们必须被派遣到创建它们的线程-UI线程。


我在后台线程中创建我的PathGeometry对象,将它们存储并传递到主UI线程。你是说我应该只在UI线程中创建它们,然后从那里处理它们吗?我认为只要我创建并传递了它们,我就可以在UI线程中与它们交互。 - user1842853
不行,你必须在UI线程上创建它们,否则你的UI线程无法访问它们。 - Simon Wood
1
好的,我已经完成了上述工作并且它可以正常运行- 非常感谢!我可以在后台线程上创建大量其他对象并在UI线程上访问它们- 只是因为PathGeometry和Path对象是基于UI的,因此必须在UI线程上创建它们吗? - user1842853

1

您正在后台线程上创建PathGeometry对象,因此arc.pathGeometry.Dispatcher将为您提供后台线程的Dispatcher,而不是UI线程的。

您需要将处理过程放在UI dispatcher上,可以像这样实现 -

App.Current.Dispatcher.BeginInvoke((Action)(() =>
{
    MessageBox.Show(arc.pathGeometry.ToString());
}));

谢谢您的回复。我在UI线程上尝试了上述操作,但仍然收到关于另一个线程拥有该对象的错误,这让我感到困惑,因为这样做是有道理的! - user1842853
好的。所以解决方案是在UI线程上创建UI组件,或者在访问UI线程上的'PathGeometry'对象之前调用Freeze方法。 - Rohit Vats
是的,那是有道理的。基于我的目的,我想我只需要在UI线程上创建它们。 - user1842853

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接