1

根据我们的要求,我们必须在新的 UI 线程中打开一个 WPF 窗口。

我们使用以下代码在主 UI 线程的新 UI 线程中打开窗口:

Thread winthread = new Thread(new ThreadStart(() =>
{
    SynchronizationContext.SetSynchronizationContext(
        new DispatcherSynchronizationContext(
            Dispatcher.CurrentDispatcher));
    Window windowObj = new Window();
    Grid gridObj = new Grid();
    MyUserControl ctrl = new MyUserControl();
    gridObj.Children.Add(ctrl);
    windowObj.Content = gridObj;

    windowObj.Show();
    System.Windows.Threading.Dispatcher.Run();
}));

winthread.IsBackground = true;
winthread.SetApartmentState(ApartmentState.STA);
winthread.Start();

MyUserControl执行上述代码时,窗口将显示为内容。我正在做一些动画,比如在鼠标双击事件上翻转我的用户控件。

当我双击它时,应用程序开始抛出以下异常:

调用线程无法访问此对象,因为不同的线程拥有它。

上线System.Windows.Threading.Dispatcher.Run()

谁能建议这个问题的解决方案?

4

2 回答 2

1

你上面的代码很好。无论问题是什么,它都在 MyUserControl 内部——这些类中必须有共享元素或对主线程拥有的对象的引用。您必须确保内部没有任何东西MyUserControl是在主线程上创建或拥有的,包括作为参数传递的对象等。

或者,您可能正在尝试使用主线程与(或与内部的组件)进行交互MyUserControl。如果您想ctrl从外部线程(即:主线程等)执行任何操作,您必须保留对调用的引用ctrl并使用调用 - 如下所示:

public partial class MainWindow : Window
{
    UserControl1 ctrl;

    public MainWindow()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, RoutedEventArgs e)
    {
        Thread winthread = new Thread(new ThreadStart(() =>
        {
            SynchronizationContext.SetSynchronizationContext(
                new DispatcherSynchronizationContext(
                    Dispatcher.CurrentDispatcher));
            Window windowObj = new Window();
            Grid gridObj = new Grid();
            ctrl = new UserControl1();
            gridObj.Children.Add(ctrl);
            windowObj.Content = gridObj;

            windowObj.Show();
            System.Windows.Threading.Dispatcher.Run();
        }));

        winthread.IsBackground = true;
        winthread.SetApartmentState(ApartmentState.STA);
        winthread.Start();
    }

    private void button2_Click(object sender, RoutedEventArgs e)
    {
        ctrl.Dispatcher.Invoke(new Action(() => ctrl.AddStuff()));
    }
}

在这里,我制作UserControl1了一个带有列表框的简单窗口:

public partial class UserControl1 : UserControl
{
    private int i;

    public UserControl1()
    {
        InitializeComponent();
    }

    public void AddStuff()
    {
        listBox1.Items.Add("This is line : " + i.ToString());
        i += 1;
    }
}

在上述情况下,您必须确保主线程使用调用 - 特别是它希望ctrl's Dispatcher 来处理调用。而不是使用自己的调度程序(这会导致跨线程错误),主线程将调用编组ctrl的调度程序。

如果您至少可以在MyUserControl您遇到异常的地方显示代码行,那将会有所帮助。

于 2012-11-20T12:05:35.283 回答
-1

听起来像一个调用问题:

相当容易解决,因为您尝试在不同的线程中更改网格/窗口。

更改线程以调用更改

http://social.msdn.microsoft.com/forums/en-US/wpf/thread/360540eb-d756-4434-86f9-a3449f05eb55

于 2012-11-20T11:39:11.880 回答