从另一个线程填充的对象读取数据

时间:2010-11-19 19:25:03

标签: c# multithreading object-sharing

语言:c#(wpf)

情况:我必须从文件中加载3D网格,然后填充Viewport3D。

我想做什么:我想在BackgroundWorker中加载3D网格,因此在加载3D网格时应用程序不需要停止;这需要几秒钟。

问题:问题不在于如何使用BackgroundWorker。这是有据可查的。当我想填充Viewport3D的Model3DGroup(3D对象组)时会出现问题。

从文件加载3D网格时,在后台工作器中,我填充一个自定义网格类,其中包含网格中每个对象的所有点和三角形索引。我将它们分别存储在Point3DCollections和Int32Collections中。

public class LFSMeshObject
{
    public Point3D Center;
    public int Radius;
    public int NumPoints;
    public int NumTris;

    public Color ObjectColor { get; private set; }
    public Point3DCollection Points { get; private set; }
    public Int32Collection Tris { get; private set; }

当这个填充的对象传递回GUI线程时,我可以很好地读取存储在对象中的所有值和属性。我还可以读取我复制到MeshGeometry3D中的Point3Dcollections和Int32Collections进入Model3DGroup,但后来得到一个线程所有者异常,因为后台填充对象的属性属于后台线程。

    DiffuseMaterial mDMat;
    MeshGeometry3D mGeom;
    Debug.WriteLine("num objects in mesh : {0}", _trackMesh.NumObjects);
    for (int a = 0; a < _trackMesh.NumObjects; a++)
    {
        mGeom = new MeshGeometry3D();
        mGeom.Positions = _trackMesh.TrackMeshObjects[a].Points;
        mGeom.TriangleIndices = _trackMesh.TrackMeshObjects[a].Tris;

        mDMat = new DiffuseMaterial();
        mDMat.Brush = new SolidColorBrush(_trackMesh.TrackMeshObjects[a].ObjectColor);

        // thread owner exception
        _mgTrack.Children.Add(new GeometryModel3D(mGeom, mDMat));
    }

问题是我正在读取对象(Point3DCollection / Int32Collection)而不是从背景填充对象复制的普通值吗?
是这样当你在线程之间共享数据时,你必须在另一个线程中创建你想要使用的所有数据的副本(在其他对象中,即MeshGeometry / Modelgroup)?在填充完成后,我们可以不在后台填充对象然后在另一个线程中“简单地使用它”吗?

2 个答案:

答案 0 :(得分:0)

尝试一个简单而又脏的方法是将函数指针(委托回调)传递给从gui线程启动的线程的上下文。当你想要将它读回gui线程时,该委托将基本上返回你想要阅读的任何内容。因此回调是在主线程上创建的。这应该工作。

答案 1 :(得分:0)

与此同时,我通过使用普通的Point3D []和int []数组而不是xxxCollection对应数来解决问题。然后,当我用这些数组填充3D模型时,它工作正常。没有线程所有权错误。奇怪......但显然有些对象(已在后台线程上创建)可能无法在另一个线程中访问,或者我遗漏了某些东西(可能 - 我只使用了c#1.5个月)。