0

言語: c# (wpf)

状況 : ファイルから 3D メッシュを読み込んでから、Viewport3D を作成する必要があります。

やりたいこと: 3D メッシュを BackgroundWorker にロードしたいので、3D メッシュのロード中にアプリケーションが停止する必要はありません。これには数秒かかります。

問題 : 問題は BackgroundWorker の使用方法ではありません。それは十分に文書化されています。この問題は、Viewport3D の Model3DGroup (3D オブジェクト グループ) を設定するときに発生します。

ファイルから 3D メッシュをロードするとき、バックグラウンド ワーカーで、メッシュ内の各オブジェクトのすべてのポイントと三角形のインデックスをカスタム メッシュ クラスに入力します。これらをそれぞれ Point3DCollections と Int32Collections に保存します。

public class LFSMeshObject
{
    public Point3D Center;
    public int Radius;
    public int NumPoints;
    public int NumTris;

    public Color ObjectColor { get; private set; }
    public Point3DCollection Points { get; private set; }
    public Int32Collection Tris { get; private set; }

この移入されたオブジェクトが GUI スレッドに戻されると、オブジェクトに保存されているすべての値とプロパティを問題なく読み取ることができます。また、Model3DGroup に入る MeshGeometry3D にコピーした Point3Dcollections と Int32Collections を読み取ることもできますが、バックグラウンドで設定されたオブジェクトのプロパティがバックグラウンド スレッドに属しているため、スレッド所有者の例外が発生します。

    DiffuseMaterial mDMat;
    MeshGeometry3D mGeom;
    Debug.WriteLine("num objects in mesh : {0}", _trackMesh.NumObjects);
    for (int a = 0; a < _trackMesh.NumObjects; a++)
    {
        mGeom = new MeshGeometry3D();
        mGeom.Positions = _trackMesh.TrackMeshObjects[a].Points;
        mGeom.TriangleIndices = _trackMesh.TrackMeshObjects[a].Tris;

        mDMat = new DiffuseMaterial();
        mDMat.Brush = new SolidColorBrush(_trackMesh.TrackMeshObjects[a].ObjectColor);

        // thread owner exception
        _mgTrack.Children.Add(new GeometryModel3D(mGeom, mDMat));
    }

バックグラウンドで設定されたオブジェクトからコピーされるプレーンな値ではなく、オブジェクト (Point3DCollection / Int32Collection) を読み取っているという問題はありますか?
スレッド間でデータを共有する場合、使用するすべてのデータのコピーを (他のオブジェクト、つまり MeshGeometry / Modelgroup で) 他のスレッドで作成する必要がありますか? バックグラウンドでオブジェクトを生成し、生成が完了した後、別のスレッドで「単に使用する」ことはできませんか?

4

2 に答える 2

0

それまでの間、対応する xxxCollection の代わりにプレーンな Point3D[] および int[] 配列を使用して問題を修正しました。次に、3D モデルにこれらの配列を設定すると、正常に動作します。スレッド所有権エラーはありません。奇妙な...しかし、明らかに一部のオブジェクト(バックグラウンドスレッドで作成されたもの)は別のスレッドでアクセスできないか、何かが欠けています(おそらく-C#を1.5か月しか使用していません)。

于 2010-11-19T21:13:47.587 に答える
0

簡単で汚い試みは、GUI スレッドから起動するスレッドのコンテキストに関数ポインタ (デリゲート コールバック) を渡すことです。そのデリゲートは、基本的に、読み取りたい正確な瞬間に読み取りたいものを何でも GUI スレッドに返します。したがって、コールバックはメイン スレッドで作成されます。これはうまくいくはずです。

于 2010-11-19T19:43:32.390 に答える