1

私はかなり大きなオブジェクトを作成するWPFプロジェクト(VS2010、 )を持っています(カスタムフォーマットファイルからの読み取り、情報の処理、メッシュの作成など)。これには約3〜4秒かかります。作成され、さらに2〜3秒。すること。これをすべてカスタム クラスで行い、次のメソッドを呼び出します。.NET4.0ModelVisual3DSTLmainViewport.Children.Add(ModelVisual3D)

 class My3DModel
{
...
        public MyModelVisual3D createModelVisual3D(MyTypes tType, int tNumber)
            {
                this.myModelVisual3D = new MyModelVisual3D(tType, tNumber);
                for (int i = 0, j = 0; i < this.Triangles.Length; i++)
                {
                    this.mesh.Positions.Add(this.Triangles[i].Vertex1);
                    this.mesh.Positions.Add(this.Triangles[i].Vertex2);
                    this.mesh.Positions.Add(this.Triangles[i].Vertex3);
                    this.mesh.Normals.Add(this.Triangles[i].Normal);
                    this.mesh.Normals.Add(this.Triangles[i].Normal);
                    this.mesh.Normals.Add(this.Triangles[i].Normal);
                    this.mesh.TriangleIndices.Add(j++);
                    this.mesh.TriangleIndices.Add(j++);
                    this.mesh.TriangleIndices.Add(j++);
                }
                this.model3DGroup.Children.Add(new GeometryModel3D(this.mesh, material));
                this.myModelVisual3D.Content = this.model3DGroup;
                return this.myModelVisual3D;
            }
}

戻り値も、​​私が作成したカスタム クラスです。

class ToothModelVisual3D : ModelVisual3D
{
    //VARIABLES
    private MyTypes myType;
    private int number;

    //OPERATORS
    public MyTypes MyType
    {get { return myType; } set { myType = value; }}

    public int Number
    {get { return number; } set { number = value;}}

    public ToothModelVisual3D() { }

    public ToothModelVisual3D(MyTypes tType, int tNumber) { MyType = tType; Number = tNumber; }
}

私がやりたいのは、プログラムの最初に次の1回だけです。

{
        My3DModel myModel;
        myModel = new My3DModel();
        myModel.readFileBytes("C:\\registered\\" + 1 + ".stl");
        myModel.loadTriangles();
        mainViewport.Children.Add(myModel.createModelVisual3D(MyTypes.Sometype, 1);
}

メイン スレッドで実行すると、UI がハングします。ワーカー スレッドで実行して呼び出すmainViewport.Children.Add(...)と、そのワーカー スレッドで作成されたリソースにアクセスできないと表示されます。ヘルプ?!

私が理解していることから、2 つのスレッドとそれぞれに属するリソースがあるところまで来ました ( mainViewport => UIThread & myModel => WorkerThread)。どちらのスレッドも他のリソースに直接アクセスできませんが、UIThread で myModel を作成して使用するとハングします... UI から十分な応答性を得たいだけなので、ユーザーはプログラムがモデルをロードするのを待っている間にプログラムを最小化できます、 これ以上何もない。どうやってやるの?UIThread ですべての CPU 負荷の高い作業を行う方法はありますか?リソースの競合が発生せず、その時間の UI のみを処理するワーカー スレッドを持つことはありませんか?

BackgroundWorkerPS:スレッドとTask<TResult>クラスで試しました。同じとは言わないまでも、結果は似ていました。

PPS: フルバージョンでは、30 ~ 40 秒以上ロードされる大規模なモデルがロードされます...

4

3 に答える 3

1

最近、XNA アプリケーションを WPF に移植するときに同じ問題に遭遇しました。私の場合、バックグラウンド スレッドを使用して位置、法線、およびインデックスをファイルから読み込むことで、これを部分的に解決しました。次に、同じスレッドで、GeometryModel3D と MeshGeometry3D を使用して Model3DGroup の XAML を含むメモリ ストリームを構築します。

次に、UI スレッドで、メモリ ストリームが利用可能になったら、モデルをロードします...

Model3DGroup model = System.Windows.Markup.XamlReader.Load(memoryStream) as Model3DGroup;

遅延はまだありますが、ファイル アクセスはバックグラウンド スレッドで行われるため、それほど深刻ではありません。

于 2015-02-05T00:00:47.413 に答える
0

回答が遅くなり申し訳ありませんが、実際には次の方法でずっと前に問題を回避できました。

    delegate void myDelegate();

    private void fileOpenButton_Click(object sender, RoutedEventArgs e)
    {
        try
        {
            Thread ViewportLoaderThread = new Thread(loadViewportItemsAsync);
            ViewportLoaderThread.IsBackground = true;
            ViewportLoaderThread.Start();
        }
        catch (Exception err) { UtilsProgram.writeErrorLog(err.ToString()); }
    }

    private void loadViewportItemsAsync()
    {
        try
        {
            //TRY to browse for a file
            if (!browseForFile()) return;

            Dispatcher.Invoke(new Action(() => { myStatusBar.Visibility = System.Windows.Visibility.Visible; menuItemHelpDemo.IsEnabled = false; }), null);

            //Load file, unpack, decrypt, load STLs and create ModelGroup3D objects
            UtilsDen.DenModel = new DenLoader(UtilsDen.Filename, UtilsDen.Certificate, UtilsDen.PrivateKey, this);

            //Load the models to viewport async
            myDelegate asyncDel = new myDelegate(sendModelsToViewportAsync);
            this.Dispatcher.BeginInvoke(asyncDel, null);
        }
        catch (Exception err) { MessageBox.Show(UtilsProgram.langDict["msg18"]); UtilsProgram.writeErrorLog(err.ToString()); }
    }

    private void sendModelsToViewportAsync()
    {
        for (int i = 0; i < UtilsDen.DenModel.StlFilesCount; i++)
        {
            //Add the models to MAIN VIEWPORT
            ModelVisual3D modelVisual = new ModelVisual3D();
            GeometryModel3D geometryModel = new GeometryModel3D();
            Model3DGroup modelGroup = new Model3DGroup();

            geometryModel = new GeometryModel3D(UtilsDen.DenModel.StlModels[i].MeshGeometry, UtilsDen.Material);

            modelGroup.Children.Add(geometryModel);
            modelVisual.Content = modelGroup;
            mainViewport.Children.Add(toothModelVisual);
        }
    }

重要なのはthis.Dispatcher.BeginInvoke(asyncDel, null);、メインスレッドで動作するように使用することでしたが、非同期で実行されるため、遅れることはありません。

于 2015-02-05T08:28:45.480 に答える
0

デリゲートを使用すると、UI に遅延が発生するように見えます。より良い解決策は、ワーカー スレッドでモデルを作成してからフリーズすることです。モデルは、迷惑な例外なしで UI スレッドによって複製できます。これは、ロードに 25 秒以上かかるモデルで機能します。これに関して私が見つけた唯一の問題は、モデルにテクスチャが含まれていると機能しないことです。

于 2015-05-13T23:08:56.537 に答える