如何在单独的线程中加载多个3D几何,而不会遇到线程所有权问题?

时间:2011-06-29 16:25:40

标签: c# .net wpf multithreading xaml

我有几个MeshGeometry3D元素存储在单独的文件中。例如,somemodel.xml可能包含<MeshGeometry3D ... />

如果我在主UI线程中加载它们,它们会在加载时锁定UI。所以我尝试在一个单独的线程中加载它们:

ThreadStart threadStart = delegate
{
    var geometry = ConvertXmlFileToMeshGeometry3D(filename);
    viewport2DVisual3D.Dispatcher.BeginInvoke(
        DispatcherPriority.Normal,
        new Action(delegate { viewport2DVisual3D.Geometry = geometry; }));
};
threadStart.BeginInvoke(delegate(IAsyncResult aysncResult) { threadStart.EndInvoke(aysncResult); }, null);

但是,这会在viewportVisual.Geometry = geometry;The calling thread cannot access this object because a different thread owns it.

上出现例外情况

换句话说,MeshGeometry3D是在不同的主题上创建的,所以我无法将其作为Viewport2DVisual3D的几何。

我无法找到一种方法来异步加载MeshGeometry3D,而不会被错误的线程拥有。这只是不可能的事情,还是有办法实现呢?

编辑:分析表明,加载MeshGeometry3D的时间大约有13%用于从文件(var element = XElement.Load(filename);)加载xml元素,剩下的用于将其转换为MeshGeometry3D:

return new MeshGeometry3D
{
    Normals = (Vector3DCollection)new Vector3DCollectionConverter().ConvertFromString(element.Attribute("Normals").Value),
    Positions = (Point3DCollection)new Point3DCollectionConverter().ConvertFromString(element.Attribute("Positions").Value),
    TextureCoordinates = (PointCollection)new PointCollectionConverter().ConvertFromString(element.Attribute("TextureCoordinates").Value),
    TriangleIndices = (Int32Collection)new Int32CollectionConverter().ConvertFromString(element.Attribute("TriangleIndices").Value),
};

因此,从磁盘中获取XML看起来不像是瓶颈。

1 个答案:

答案 0 :(得分:4)

除非您以后需要修改模型,否则可以在加载后尝试Freeze,然后可以在线程之间共享它,请参阅Freezable Objects Overview