簡體   English   中英

C#WPF ModelVisual3D創建時間過長,無法在單獨的線程上完成

[英]C# WPF ModelVisual3D creation takes too long and cannot be done on separate thread

我有一個WPF項目( VS2010.NET4.0 ),在其中創建了一個很大的ModelVisual3D對象(從自定義格式的STL文件讀取,處理信息,創建網格等),大約需要3-4秒。 要創建,另外2-3秒。 做一個mainViewport.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; }
}

我只想在程序開始時執行以下操作:

{
        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(...)它說它無法訪問在該工作線程上創建的資源。 救命?!

據我了解,我已經到達了兩個線程和屬於它們的資源( mainViewport => UIThread & myModel => WorkerThread )。 兩個線程都不能直接訪問另一個線程的資源,但是在UIThread上創建並使用myModel會使該線程掛起...我只想從UI上獲得足夠的響應度,因此用戶可以在等待程序加載模型的同時將其最小化,僅此而已。 我怎樣才能做到這一點? 有沒有一種方法可以在UIThread上完成所有CPU繁重的工作,因此不會出現資源沖突,並且有一個只能在該時間處理UI的工作線程?

PS:我已經嘗試過Thread, BackgroundWorkerTask<TResult>類。 如果不說相同,結果是相似的。

PPS:完整版將加載海量模型,加載時間將超過30-40秒...

在將XNA應用程序移植到WPF時,我最近遇到了相同的問題。 就我而言,我通過使用后台線程從文件加載位置,法線和索引來部分解決此問題。 然后在同一線程中,使用GeometryModel3D和MeshGeometry3D為Model3DGroup構造一個包含XAML的內存流。

然后,在UI線程中,一旦內存流可用,就加載模型...

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

仍然存在延遲,但是由於文件訪問是在后台線程中完成的,因此並不那么嚴重。

很抱歉,您的回答很晚,但是很久以前,我實際上可以通過以下方法解決該問題:

    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); 因為它是異步執行的,所以它在主線程上工作,但不會滯后。

使用委托似乎仍然會在UI上引入滯后,更好的解決方案是在工作線程中創建模型,然后凍結它。 然后可以通過UI線程克隆模型,而不會產生煩人的異常。 這適用於需要25秒或更長時間加載的模型。 我發現的唯一問題是,如果模型包含紋理,則它不起作用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM