1

私はhelix-toolkitというライブラリを使用していますが、私には負担があるので、ここに特別なケースのビットがあります。3Dモデル作成を並列化する方法は?

私は、背景作業者を使用してコード内にモデルオブジェクトの作成を並列化したいと思います。

私は、mutlithreadingとUI要素の作業に大きな問題があることを知っていますが、何らかの理由で回避策があります。私はBackgroundwokerを作成する

まずファイル、Geometry3Dオブジェクトを作成し、最終的にビューポートにジオメトリをバインドするSetModelGeometryを呼び出すためのワークロードを分割:

は、ここに私のコードの概略構成です。 2番目のファイルは、バインディングの実行方法を示しています。

MainWindow.xaml.cs

private void Draw_Building() 
     { 
      _worker = new BackgroundWorker { WorkerReportsProgress = true, WorkerSupportsCancellation = true }; 
      _worker.DoWork += Draw_Building_DoWork; 
      _worker.ProgressChanged += DrawBuilding_ProgressChanged; 
      _worker.RunWorkerCompleted += DrawBuilding_RunWorkerCompleted; 
      _worker.RunWorkerAsync(10000); 

     } 

     private void Draw_Building_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e) 
     { 
      // returns a list containing Geometry3D objects (created by meshBuilder.ToMeshGeometry3D()) 
      Geometryhandler.Draw_Building(sender, e); 
     } 

     private void DrawBuilding_ProgressChanged(object sender, ProgressChangedEventArgs e) 
     { 
      StatusProgressBar.Value = e.ProgressPercentage; 
      var i = (int)e.UserState; 
      var actualComponent = MyBuildingComponents.First(c => c.Id == i); 
      LblStatusbarInfo.Text = "Currently meshing element #" + actualComponent.Globalid + " (" + 
            actualComponent.Objectname + ")"; 
      StatusProgressbarMsg.Text = "Meshing (" + e.ProgressPercentage + " %)"; 
     } 

     private void DrawBuilding_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
     { 
      StatusProgressbarMsg.Text = "-"; 
      StatusProgressBar.Value = 0; 
      LblStatusbarInfo.Text = "Meshing completed."; 

      Geometry = e.Result as List<MeshIdandGeometry>; 

      // creates MeshGeometryModel3D objects and binds them to the viewport using the List of Geometries 
      MainViewModel.SetModelGeometry(Geometry); 

     } 

MainViewModel.cs

public void SetModelGeometry(List<MeshIdandGeometry> geometry) 
    { 

     MyModelGeometry = new Element3DCollection(); 

     if (geometry != null) 
     { 
      foreach (var mygeometry in geometry) 
      { 

       var s = new MeshGeometryModel3D 
       { 
        Geometry = mygeometry.Geometry, 
        Material = mygeometry.Material, 
       }; 
       this.MyModelGeometry.Add(s); 

       s.Attach(MyModelViewport.RenderHost); 
      } 

     } 

     this.OnPropertyChanged("MyModelGeometry"); 
    } 

現時点では私の問題は、次のエラーメッセージです:

呼び出し元のスレッド広告のためこのオブジェクトにアクセスできませんそれ以外の場合 スレッドが所有しています。

ModelGeometryをビューポートに接続しようとすると、SetModelGeometry関数でスローされます。

私は、ジオメトリが別のスレッドで作成されていて、今アクセスできていないということについてコンパイラが不平を言っていると思います。

DrawBuilding関数の並列実行を破壊しないで回避策や解決策はありますか?

はEDIT:

EDIT 2:GeometryhandlerDraw_Building方法

Draw_Building方法の間違ったバージョンを掲載:

public void Draw_Building(object sender, DoWorkEventArgs e) 
    { 

     var geometry = new List<MeshIdandGeometry>(); 

     var standardMaterial = new PhongMaterial() 
     { 
      AmbientColor = SharpDX.Color.LightGray, 
      //DiffuseColor = new Color4(0.35f, 0.35f, 0.35f, 1.0f), 
      //DiffuseMap = new BitmapImage(new System.Uri(@"Con_Diffuse_2.jpg", System.UriKind.RelativeOrAbsolute)), 
      //NormalMap = new BitmapImage(new System.Uri(@"Con_Normal_2.jpg", System.UriKind.RelativeOrAbsolute)), 
     }; 

     var max = _mainWindow.MyBuildingComponents.Count; 
     var i = 1; 

     // Loop over building components 
     foreach (var component in _mainWindow.MyBuildingComponents) 
     { 

      //if (i == 5) break; 
      var component1 = component; 
      var componentTriangles = _mainWindow.MyTriangles.Where(triangle => triangle.ComponentId == component1.Id); 

       var meshBuilder = new MeshBuilder(true, true, true); 

      // Loop over triangles in building element 
      foreach (var triangle in componentTriangles) 
      { 
       var triangle1 = triangle; 

       var p1 = _mainWindow.MyVertices.Find(
        vt => vt.Id == triangle1.PointId1); 
       var p2 = _mainWindow.MyVertices.Find(
        vt => vt.Id == triangle1.PointId2); 
       var p3 = _mainWindow.MyVertices.Find(
        vt => vt.Id == triangle1.PointId3); 
       if (p1 != null && p2 != null && p3 != null) 
       { 
        //meshBuilder.AddTriangle(new Vector3((float)p1.X, (float)p1.Y, (float)p1.Z), 
        // new Vector3((float)p2.X, (float)p2.Y, (float)p2.Z), 
        // new Vector3((float)p3.X, (float)p3.Y, (float)p3.Z)); 

        // coordination are switched to match the coordinate system in SharpDX viewport 
        meshBuilder.AddTriangle(new Vector3(-(float)p1.Y, (float)p1.Z, -(float)p1.X), 
         new Vector3(-(float)p2.Y, (float)p2.Z, -(float)p2.X), 
         new Vector3(-(float)p3.Y, (float)p3.Z, -(float)p3.X)); 
       } 
      } 
      var mesh = meshBuilder.ToMeshGeometry3D(); 

      var meshandtriangle = new MeshIdandGeometry 
      { 
       Id = component1.Id, 
       Geometry = mesh, 
       Material = standardMaterial, 
      }; 
      geometry.Add(meshandtriangle); 

      i++; 
      var progressPercentage = Convert.ToInt32(((double)i/max) * 100); 
      var backgroundWorker = sender as BackgroundWorker; 
      backgroundWorker?.ReportProgress(progressPercentage, component1.Id); 
     } 

     e.Result = geometry; 

    } 
+0

フリーズとクローンを試してください – egse

+0

こんにちはegse、申し訳ありません私は今あなたのコメントを見ました。どうすればそれを使うのですか?私は、フリーズがMedia3D.GeometryModel3Dオブジェクトのために実装されているのを見ましたが、sharpDXブランチが使用しているモデルオブジェクトの等価物を見つけませんでした。 – Daniel

+0

はい、あなたは正しいです。それで、私はそれがエラーを引き起こす幾何学ではなくマテリアルであると思う。 私にGeometryhandler.Draw_Buildingメソッドの内容を表示すると、私はもっと助けることができます。 – egse

答えて

1

ビッグおかげで解決策を見つけるために@egseします。問題の原因となるコードの

パート:

var standardMaterial = new PhongMaterial() 
    { 
     AmbientColor = SharpDX.Color.LightGray, 
     //DiffuseColor = new Color4(0.35f, 0.35f, 0.35f, 1.0f), 
     //DiffuseMap = new BitmapImage(new System.Uri(@"Con_Diffuse_2.jpg", System.UriKind.RelativeOrAbsolute)), 
     //NormalMap = new BitmapImage(new System.Uri(@"Con_Normal_2.jpg", System.UriKind.RelativeOrAbsolute)), 
    }; 

基本的には上記のコードの問題は材料をのBackgroundWorkerの範囲内のローカル変数として作成されることです。 UIスレッドがマテリアルオブジェクトを入力しようとすると、所有権に問題が発生します。

この問題の解決策は、マテリアルがUIスレッドによって作成されていることを確認することです。このケースでは、Geometryhandlerのコンストラクタ)

TL; DR:UIとは別のスレッドでDependencyObjectから継承するクラスのインスタンスを作成しないでください。

関連する問題