语言: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)?在填充完成后,我们可以不在后台填充对象然后在另一个线程中“简单地使用它”吗?
答案 0 :(得分:0)
尝试一个简单而又脏的方法是将函数指针(委托回调)传递给从gui线程启动的线程的上下文。当你想要将它读回gui线程时,该委托将基本上返回你想要阅读的任何内容。因此回调是在主线程上创建的。这应该工作。
答案 1 :(得分:0)
与此同时,我通过使用普通的Point3D []和int []数组而不是xxxCollection对应数来解决问题。然后,当我用这些数组填充3D模型时,它工作正常。没有线程所有权错误。奇怪......但显然有些对象(已在后台线程上创建)可能无法在另一个线程中访问,或者我遗漏了某些东西(可能 - 我只使用了c#1.5个月)。