WPF – I’m using BackgroundWorker to create a Model3D object, but when I want to add it to a Model3DGroup that is defined in the XAML, I get exception:
Cannot use a DependencyObject that belongs to a different thread than its parent Freezable.
This is the whole code behind:
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;
}
}
and this is the whole 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>
In your RunWorkerCompleted handler you’re adding a GeometryModel3D instance to a Model3DGroup, which was obviously created in a thread other than the UI thread, since the BackgroundWorker.DoWork handler is executed in a separate thread.
In short, WPF does not allow this, as you might have noticed from the exception message. All UI elements, or to be more precise, all DispatcherObject-derived objects in your application must be created in the same thread.
Get an overview of the WPF Threading Model and also see the Remarks section in the BackgroundWorker documentation.
EDIT: you could however create new GeometryModel3D instances by synchronously invoking the Dispatcher of your MainWindow class (without having tested that):