0

I have to load a XAML file, but since it function only in context of a STA thread, I have to start a new thread and set the apartment state of it to STA.

After control is loaded I want to get all its logical children with LogicalTreeHelper.GetChildren( ... ).

At that point I get System.InvalidOperationException with the Message=The calling thread cannot access this object because a different thread owns it.

The code:

public partial class MainWindow : Window
{
    private Thread STAThread = null;
    /// <summary>
    /// XAML path.
    /// </summary>
    private static string _selectedXAML = Path.GetFullPath( @"..\..\Resources\UserControl1.xaml" );

    private FrameworkElement _loadedUI = null;

    public MainWindow()
    {
        InitializeComponent();
    }

    private void MainWindow_OnLoaded( object sender, RoutedEventArgs e )
    {
        this.LoadUI();
        DependencyObject depObj = _loadedUI as DependencyObject;

        var s = LogicalTreeHelper.GetChildren( depObj );
    }

    private void LoadUI()
    {
        // Read the text as string from the file
        var xamlText = File.ReadAllText( _selectedXAML );

        // Replace variable values and script value pairs
        StringReader stringReader = new StringReader( xamlText );
        XmlReader xmlReader = XmlReader.Create( stringReader );

        STAThread = new Thread(
            () =>
            {
                _loadedUI = XamlReader.Load( xmlReader ) as FrameworkElement;
            } );


        STAThread.SetApartmentState( ApartmentState.STA );

        STAThread.Start();

        STAThread.Join();
    }
}

So how can I change the object’s thread owner?

Tying to invoke any of Dispatcher's "Invoke" methods on window object don't help.

Stefan Fachmann
  • 555
  • 1
  • 5
  • 18

1 Answers1

0

You can't change the owning thread. Instead you may simplify your LoadUI method.

Drop all the separate thread stuff and load the XAML directly, as the Join call would block your UI thread anyway until the load thread has finished.

private FrameworkElement LoadUI()
{
    // Read the text as string from the file
    var xamlText = File.ReadAllText(_selectedXAML);

    // Replace variable values and script value pairs
    var stringReader = new StringReader(xamlText);
    var xmlReader = XmlReader.Create(stringReader);

    return XamlReader.Load(xmlReader) as FrameworkElement;
}

private void MainWindow_OnLoaded(object sender, RoutedEventArgs e)
{
    var s = LogicalTreeHelper.GetChildren(LoadUI());
}
Clemens
  • 123,504
  • 12
  • 155
  • 268