【问题标题】:Problems with multi-threading windows in WPFWPF中多线程窗口的问题
【发布时间】:2012-08-28 07:39:57
【问题描述】:

我正在像this 这样的新线程中打开新的 WPF 窗口:

private void OnCreateNewWindow(object sender, RoutedEventArgs e)
{
    Thread thread = new Thread(() =>
    {
        Window1 w = new Window1();
        w.Show();
        Dispatcher.Run(); 
    });

    thread.SetApartmentState(ApartmentState.STA);
    thread.Start();
    }
}

问题是它卡在 Show-method 上(不显示窗口)并且永远不会到达 Dispatcher.Run。

检查线程和调用堆栈时,我可以看到两个线程,Main 和我的新窗口线程。窗口线程的调用栈位于以下帧:

PresentationCore.dll!System.Windows.Input.CommandManager.FindCommandBinding(对象 发件人,System.Windows.RoutedEventArgs e, System.Windows.Input.ICommand command, bool execute) + 0x1c0 bytes

在尝试修改代码时,我曾经设法得到一条异常消息:

不能使用属于不同线程的 DependencyObject 它的父级 Freezable。

我感觉这与访问未被冻结的主线程拥有的资源有关。在这个应用程序中,我有很多通用样式和资源、画笔等,但我试图通过将以下内容放在窗口的构造函数中来避免在这个特定对话框中使用它们:

InheritanceBehavior = InheritanceBehavior.SkipAllNow;

但这似乎还不够。不知何故,似乎无论如何都访问了一些不允许的资源。

带有 FindCommandBinding 的框架暗示它可能是命令绑定的问题。但是这个对话框没有命令绑定。

如果资源字典中定义了像画笔这样的资源,它们是否会被隐式冻结?如果没有,我如何以简单的方式明确冻结它们?有数百个刷子。但这可能不是这里的问题。

还有其他想法吗?

【问题讨论】:

  • 正如您已经假设的那样,这肯定是两个调度程序线程之间共享资源的问题。像画笔这样的资源不会被隐式冻结。但是,您可以在 XAML 中声明的 Freezable 对象上设置 PresentationOptions:Freeze="True"。请参阅 Freezing from Markup 部分here
  • 为什么还要创建一个新线程?
  • 我已经尝试冻结我所有的画笔,但这并没有帮助。无论如何,我认为在使用 SkipAllNow 时不应加载它们。很奇怪。

标签: wpf multithreading window


【解决方案1】:

您需要使用 Dispatcher.Invoke 或 BegingInvoke 方法来执行 winodw 对象的创建和调用 show 方法。工作线程无法调用或更新控件。

Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, () => new Thread(() =>     { Window1 w = new Window1();         w.Show();})

【讨论】:

  • 我不确定你的意思?我有一个调度程序(带有一个线程),我正在从这个调度程序创建一个新线程。我不需要调用线程创建。在这个新的调度程序/线程中调用窗口和显示方法。为什么我需要在这里使用调用?
  • @pcajer 阅读this
  • 那里没有调用?但是 SetSynchronizationContext 对我来说是新的。我试过了,但没有帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-28
  • 1970-01-01
  • 2023-03-08
相关资源
最近更新 更多