2011-06-29 40 views
1

我有幾個MeshGeometry3D元素存儲在單獨的文件中。例如,somemodel.xml可能包含<MeshGeometry3D ... />如何在單獨的線程中加載多個3D幾何而不會遇到線程所有權問題?

如果我在主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 s沒有他們被錯誤的線程擁有。這只是不可能的事,或者有辦法做到嗎?

編輯:探查表明的時間的約13%至加載MeshGeometry3D花費從文件(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

什麼是「鎖定」UI的操作?從磁盤獲取XML花費的時間,還是將XML轉換成幾何對象所用的時間,或者是什麼? (我問的原因是因爲可能有一些方法可以使用基於任務的異步將工作分解成更小的部分,然後可以在UI線程上按順序完成,但不會使UI消息循環不足。) –

+0

@Eric Lippert我認爲問題不在於UI線程阻塞,而是WPF要求某些操作在UI線程上,這當然也會導致UI線程阻止:) – Matt

+0

@Eric:請參閱我的編輯。根據我的分析,從磁盤獲取XML並將其轉換爲「XElement」僅佔總時間的13%,以從文件加載「MeshGeometry3D」。 –

回答

2

除非您需要稍後修改模型,否則您可以嘗試在加載後嘗試Freeze,那麼它可以跨線程共享,請參閱Freezable Objects Overview

+0

謝謝,以後我不需要修改模型,所以這個工作很完美。 –