开发者

reading data from an object that is populated from another thread

开发者 https://www.devze.com 2023-01-25 19:47 出处:网络
The language : c# (wpf) The situation : I have to load a 3D mesh from a file after which I populate a Viewport3D.

The language : c# (wpf)

The situation : I have to load a 3D mesh from a file after which I populate a Viewport3D.

What do I want to do : I want to load the 3D mesh in a BackgroundWorker, so the application does not need to stall while loading the 3D mesh; this takes a few seconds.

The problem : The problem is NOT how to use BackgroundWorker. That's well documented. The problem arises when I want to populate the Viewport3D's Model3DGroup (3D object group).

When loading the 3D mesh from the file, in the background worker, I populate a custom mesh class with all the points and triangle indices of each object in the mesh. I store these in Point3DCollections and Int32Collections respectively.

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; }

When this populated object is passed back to the GUI thread, I can read all values and properties stored in the object just fine. I can also read the Point3Dcollections and Int32Collections which I copy into MeshGeometry3D's which go into the Model3DGroup, but then get a thread owner exception, because the properties of the background populated object belong to the background thread.

    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();
    开发者_如何学Python    mDMat.Brush = new SolidColorBrush(_trackMesh.TrackMeshObjects[a].ObjectColor);

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

Is the problem that I'm reading objects (Point3DCollection / Int32Collection) instead of plain values which would be copied, from the background-populated object?

Is it so that when you share data between threads, you have to create copies of all the data you want to use (in other object ie. MeshGeometry / Modelgroup) in the other thread? Can we not populate an object in the background and then 'simply use it' in another thread, after population is complete?


An easy and dirty thing to try is to pass a function pointer (delegate callback) to the context of the thread you start up from the gui thread. That delegate will essentially return whatever that is that you want to read at exact moment when you want to read it back to the gui thread. So the callback is created on the main thread. This should work.


In the meantime I've fixed the problem by using plain Point3D[] and int[] arrays instead of the xxxCollection counterparts. Then when I populate the 3D models with those arrays it works fine. No thread ownership errors. Weird ... but apparently some objects (that have been created on the background thread) can simply not be accessed in another thread, or I'm missing something (probably - I've only been using c# for 1.5 months).

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号