无法访问主线程上的对象

时间:2016-06-09 14:45:39

标签: c# .net wpf thread-synchronization

所以我的申请如下:

主线程:

  1. 创建新的object1,在其构造函数中启动Thread1。
  2. 实例化object2,包含Vector3D和AxisAngleRotation3D(以及其他内容)
  3. 做事
  4. Thread1尝试访问object2.Position(Vector3D)和object2.Orientation(AxisAngleRotation3D)。位置正常,Orientation.Angle抛出System.InvalidOperationException'说"调用线程无法访问该对象,因为另一个线程拥有它"。
  5. 这两个属性都是在主线程中创建的,并且它只是提供错误的AxisAngleRotation3D.Angle,Axis和InternalQuaternion。调试,我可以确认AxisAngleRotation3D对象是在MainThread中创建的,并且无法在我的代码中找到任何可以再次访问它的地方,我已经评论了它所在的唯一一行'改变了,所以它唯一做的就是实例化。

    我完全迷失在这里。难道我不能访问在父线程中创建的对象吗?它适用于我创建的其他线程。

    有什么方法可以看到哪个线程拥有抛出异常的对象,或者在我自己的代码之外更改AxisAngleRotation3D属性时进行调试?

    我用ThreadPool.QueueUserWorkItem打开线程

    由于

1 个答案:

答案 0 :(得分:0)

问题看起来已经说明了:

  • 在主线程(线程0)上创建的对象
  • 尝试从线程1访问对象:抛出InvalidOperationException

最重要的是,如果您需要跨线程访问UI对象,您有几个选项:

  • 如果对象是Freezable并且您不打算更改它的值,则可以将其冻结。 (向量和旋转是可冻结的)
  • 否则,您可以使用依赖项对象的调度程序来访问值

冻结对象

if(freezable.CanFreeze)
{
    freezable.Freeze();
}

此时您可以读取任何线程上的对象 - 但您无法再次编辑它们。您可以通过调用Clone()方法获取该类的未冻结副本并对其进行操作,但不能更改冻结对象上的值。

使用调度程序

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),那么你必须暂停这个线程,在调度程序上排队工作并在完成后返回。