加载控件抛出调用线程无法访问此对象...

时间:2013-12-13 08:56:11

标签: c# wpf multithreading dispatcher

我必须加载一个XAML文件,但由于它仅在STA线程的上下文中起作用,我必须启动一个新线程并将其公寓状态设置为STA。

加载控件后,我想用LogicalTreeHelper.GetChildren(...)获取所有逻辑子代。

此时我得到带有Message =的System.InvalidOperationException。调用线程无法访问此对象,因为另一个线程拥有它。

代码:

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();
    }
}

那么如何更改对象的线程所有者?

在窗口对象上绑定调用任何Dispatcher的“Invoke”方法没有帮助。

1 个答案:

答案 0 :(得分:0)

您无法更改拥有的主题。相反,您可以简化LoadUI方法。

删除所有单独的线程并直接加载XAML,因为Join调用将阻止您的UI线程,直到加载线程完成。

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());
}