6

WPF-BackgroundWorkerを使用してModel3Dオブジェクトを作成していますが、XAMLで定義されているModel3DGroupに追加したい場合、例外が発生します。

親のFreezableとは異なるスレッドに属するDependencyObjectを使用することはできません。

これは背後にあるコード全体です:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        BackgroundWorker bw = new BackgroundWorker();
        bw.DoWork += bw_DoWork;
        bw.RunWorkerCompleted += bw_RunWorkerCompleted;
        bw.RunWorkerAsync();
    }

    private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        GeometryModel3D geometryModel3D = (GeometryModel3D)e.Result;
        model3DGroup.Children.Add(geometryModel3D);
    }

    private void bw_DoWork(object sender, DoWorkEventArgs e)
    {
        GeometryModel3D geometryModel3D = new GeometryModel3D();
        e.Result = geometryModel3D;
    }
}

これはXAML全体です。

    <Grid>
    <Viewport3D Margin="4,4,4,4" Grid.Row="0" Grid.Column="0">
        <ModelVisual3D>
            <ModelVisual3D.Content>
                <Model3DGroup x:Name="model3DGroup">
                </Model3DGroup>
            </ModelVisual3D.Content>
        </ModelVisual3D>
    </Viewport3D>
</Grid>
4

3 に答える 3

2

RunWorkerCompletedハンドラーでは、GeometryModel3DインスタンスをModel3DGroupに追加します。これは、BackgroundWorker.DoWorkハンドラーが別のスレッドで実行されるため、明らかにUIスレッド以外のスレッドで作成されたものです。

つまり、例外メッセージから気付いたかもしれないので、WPFはこれを許可しません。すべてのUI要素、より正確には、アプリケーション内のすべてのDispatcherObjectから派生したオブジェクトは、同じスレッドで作成する必要があります。

WPFスレッドモデルの概要を取得し、 BackgroundWorkerドキュメントの「備考」セクションも参照してください。

編集:ただし、MainWindowクラスのDispatcherを同期的に呼び出すことで(テストせずに)新しいGeometryModel3Dインスタンスを作成できます。

private void bw_DoWork(object sender, DoWorkEventArgs e)   
{   
    e.Result = Dispatcher.Invoke(
       (Func<GeometryModel3D>)(() => new GeometryModel3D()));
}   
于 2012-07-08T15:24:23.693 に答える
1

私の状況では、新しいディスパッチャスレッドに新しいWPFウィンドウを作成していました。

すべてが最小限のWPFプロジェクトで完全に機能しましたが、これと同じコードを大規模な本番WPFコードベースに移植すると、失敗しました。

問題は、間違ったスレッドで何かにバインドしている継承されたオブジェクトがあったことでした。

影響を受けるUserControlでこれを使用して、このエラーを回避できました。

public MyUserControl()
{
    // Discard all inherited styles.
    this.InheritanceBehavior = InheritanceBehavior.SkipAllNow;

    this.InitializeComponent();
}

これで動作するようになったので、この問題の原因となっている別のスレッドへの非表示のバインディングがあるスタイルまたはアタッチされたプロパティを見つけることができます。

アップデート

問題は、一部のリソースが凍結されていないことです。問題のあるリソースはここで参照されます:

ResourceDictionary resources = Application.Current.Resources;
foreach (var resource in resources)
{
   // The offending resource (a scrollbar) is listed here.                
}
于 2016-11-03T17:49:22.797 に答える
0

別のスレッドでModel3Dジオメトリを作成できます。ただし、作成後にフリーズします。RunWorkerCompletedメソッドは、フリーズされたジオメトリを単純に複製できます(ただし、Model3Dにテクスチャが含まれている場合、これを機能させることはできませんでした)。

于 2015-05-12T23:32:34.057 に答える