无法访问主线程上的对象
Can't access object on main thread
所以我的应用程序如下:
主线程:
- 创建新对象 1,它在其构造函数中启动 Thread1。
- 实例化 object2,它包含一个 Vector3D 和一个 AxisAngleRotation3D(除其他外)
- 做事
- Thread1 尝试访问 object2.Position (Vector3D) 和 object2.Orientation (AxisAngleRotation3D)。位置没问题,Orientation.Angle 抛出 'System.InvalidOperationException' 说 "Calling thread cannot access the object because another thread owns it"。
这两个属性都是在主线程中创建的,只有 AxisAngleRotation3D.Angle、Axis 和 InternalQuaternion 会出错。调试,我可以确认 AxisAngleRotation3D 对象是在 MainThread 中创建的,并且在我的代码中找不到任何再次访问它的地方,我已经注释了它唯一更改的行,所以它唯一做的就是实例化.
我完全迷失在这里。我不应该能够访问在父线程中创建的对象吗?它适用于我以类似方式创建的其他线程。
有什么方法可以查看哪个线程拥有引发异常的对象,或者在我自己的代码之外更改 AxisAngleRotation3D 属性时进行调试?
我用 ThreadPool.QueueUserWorkItem
打开线程
谢谢
问题好像已经说明了:
- 在主线程(线程 0)上创建的对象
- 试图从线程 1 访问对象:抛出 InvalidOperationException
底线是,如果您需要跨线程访问 UI 对象,您有几个选择:
- 如果对象是
Freezable
并且您不打算更改它的值,则可以将其冻结。 (向量和旋转是可冻结的)
- 否则,您可以使用依赖对象的调度程序来访问值
冻结对象
if(freezable.CanFreeze)
{
freezable.Freeze();
}
此时您可以在任何线程上读取对象--但不能再次编辑它们。您可以通过调用 Clone()
方法并对其进行操作来获取 class 的未冻结副本,但您不能更改已冻结对象的值。
使用调度程序
Freezable 对象也是 DependencyObjects
所以这适用于 UI 层中的任何对象:
var myAngle = myRotation.Dispatcher.CheckAccess()
? myRotation.Orientation.Angle
: (double)myRotation.Dispatcher.Invoke(() => myRotation.Orientation.Angle);
当然,如果你所在的线程是UI线程(Dispatcher.CheckAccess() == true
)那么你就不用担心访问属性。如果它是任何其他线程 (Dispatcher.CheckAccess() == false
),那么您必须暂停该线程,在调度程序上排队工作,并在完成后 return。
所以我的应用程序如下:
主线程:
- 创建新对象 1,它在其构造函数中启动 Thread1。
- 实例化 object2,它包含一个 Vector3D 和一个 AxisAngleRotation3D(除其他外)
- 做事
- Thread1 尝试访问 object2.Position (Vector3D) 和 object2.Orientation (AxisAngleRotation3D)。位置没问题,Orientation.Angle 抛出 'System.InvalidOperationException' 说 "Calling thread cannot access the object because another thread owns it"。
这两个属性都是在主线程中创建的,只有 AxisAngleRotation3D.Angle、Axis 和 InternalQuaternion 会出错。调试,我可以确认 AxisAngleRotation3D 对象是在 MainThread 中创建的,并且在我的代码中找不到任何再次访问它的地方,我已经注释了它唯一更改的行,所以它唯一做的就是实例化.
我完全迷失在这里。我不应该能够访问在父线程中创建的对象吗?它适用于我以类似方式创建的其他线程。
有什么方法可以查看哪个线程拥有引发异常的对象,或者在我自己的代码之外更改 AxisAngleRotation3D 属性时进行调试?
我用 ThreadPool.QueueUserWorkItem
打开线程谢谢
问题好像已经说明了:
- 在主线程(线程 0)上创建的对象
- 试图从线程 1 访问对象:抛出 InvalidOperationException
底线是,如果您需要跨线程访问 UI 对象,您有几个选择:
- 如果对象是
Freezable
并且您不打算更改它的值,则可以将其冻结。 (向量和旋转是可冻结的) - 否则,您可以使用依赖对象的调度程序来访问值
冻结对象
if(freezable.CanFreeze)
{
freezable.Freeze();
}
此时您可以在任何线程上读取对象--但不能再次编辑它们。您可以通过调用 Clone()
方法并对其进行操作来获取 class 的未冻结副本,但您不能更改已冻结对象的值。
使用调度程序
Freezable 对象也是 DependencyObjects
所以这适用于 UI 层中的任何对象:
var myAngle = myRotation.Dispatcher.CheckAccess()
? myRotation.Orientation.Angle
: (double)myRotation.Dispatcher.Invoke(() => myRotation.Orientation.Angle);
当然,如果你所在的线程是UI线程(Dispatcher.CheckAccess() == true
)那么你就不用担心访问属性。如果它是任何其他线程 (Dispatcher.CheckAccess() == false
),那么您必须暂停该线程,在调度程序上排队工作,并在完成后 return。