C# 无法使用DependencyObject,该对象属于与其父Freezable-prism不同的线程
我在开发WPF应用程序时遇到了一个问题。 该应用程序基于Prism。 应用程序使用prism引导器和 在加载任何窗口之前,应用程序会在不同的线程(STA)上打开一个模式对话框, 然后加载一堆东西(服务等) 该对话框在此期间打开,允许向用户通知应用程序启动过程的进度(使用事件聚合器传递更新)。 加载完成后,bootstraper关闭对话框并打开主应用程序窗口。 到现在为止,一直都还不错。。。 然后,当关闭应用程序时,同样的事情也在发生。 关闭主窗口,打开对话框(再次在新STA线程上),以允许通知。 但是现在,当点击ShowDialog调用(发生在新STA线程中)时, 提出了一个例外情况: “不能使用属于与其父Freezable不同线程的DependencyObject”。 经过长时间的调试,我发现异常的原因是窗口的背景,它是从应用程序级别的合并字典(在wpf UI线程上实例化)中获取的画笔/图像。 如果在没有资源字典的情况下加载图像-一切都很顺利C# 无法使用DependencyObject,该对象属于与其父Freezable-prism不同的线程,c#,wpf,multithreading,prism,sta,C#,Wpf,Multithreading,Prism,Sta,我在开发WPF应用程序时遇到了一个问题。 该应用程序基于Prism。 应用程序使用prism引导器和 在加载任何窗口之前,应用程序会在不同的线程(STA)上打开一个模式对话框, 然后加载一堆东西(服务等) 该对话框在此期间打开,允许向用户通知应用程序启动过程的进度(使用事件聚合器传递更新)。 加载完成后,bootstraper关闭对话框并打开主应用程序窗口。 到现在为止,一直都还不错。。。 然后,当关闭应用程序时,同样的事情也在发生。 关闭主窗口,打开对话框(再次在新STA线程上),以允许通知。
总结: 只有在使用resourceDictionary时,并且只有在第二次调用新的STA线程时才会观察到异常,而新的STA线程反过来会加载一个对话框,并在调用ShowDialog时引发异常 如果只有一个对话框(例如,启动时没有对话框,关闭过程中只有对话框),则不会发生异常
我的问题是:原因是什么?在这种情况下,这种例外情况究竟意味着什么? (我知道通常会有一些来自其他线程的UI线程更新,但我不明白为什么这只发生在dialgo+线程的第二个实例上)
谢谢:)我对此也有类似的问题。我不确定你是如何实现后台的。我可以试着解释一下我的情况,也许你能从中得到些什么。我创建了自己的基础窗口,我们称之为MyWindow,它继承自Windows。即
public class MyWindow : Window
{
}
我要做的是从应用程序资源字典的动态资源中应用背景
我首先选择了这个答案
public class MyWindow : Window
{
public MyWindow()
{
this.SetResourceReference(BackgroundProperty, "MyResourceKey");
}
}
当资源是一个固定颜色的ie时,这对我来说很有效
<SolidColorBrush x:Key="MyResourceKey" Color="White"/>
现在您有了对象,但它需要是一个依赖对象。我还没试过,但你也许能做到
DependencyObject temp = (DependencyObjet)this.TryFindResource("MyResourceKey");
现在您有了依赖项对象!这就是导致可自由释放父线程问题的原因。现在我们调用这个对象上的调度程序。我最终得到了这样的结果。这对我很管用,但我可能会尝试清理一下
public class MyWindow: Window
{
public MyWindow()
{
SetResources();
}
private void SetResources()
{
DependencyObject dependencyObject;
object temp;
temp = this.TryFindResource("MyResourceKey");
if (temp != null)
{
if (temp is DependencyObject)
{
dependencyObject = (DependencyObject)temp;
if (!dependencyObject.CheckAccess())
{
dependencyObject.Dispatcher.BeginInvoke(new System.Action(() => { this.SetResources(); }));
}
else
{
this.SetValue(BackgroundProperty, temp);
}
}
}
}
}
现在,这只是设置背景属性。我相信这对一种风格来说应该是一样的。所以你可以
this.SetValue(StyleProperty, temp)
花了一点时间才弄明白。但一旦我开始工作,我就兴奋不已。我们的资源使用的依赖项对象似乎遇到了线程问题,因此它是第一次加载,而不是第二次加载。第一次它在正确的线程上,但是在一路上的某个地方另一个线程被触发。还没弄明白这一点。如果有人对此有更好的解决方案,我很乐意看到 正如您正确提到的,您的背景对象是在主UI线程上创建的。您的背景实际上是一个笔刷对象,而笔刷是一个从属对象 创建DependencyObject时,它“依赖”于创建它的STA线程。因此,与其他依赖项对象一样,它只能在自己的线程上使用。这意味着STA和旧COM对象模型的某种兼容性 因此,当您尝试在另一个STA线程上使用它时,您会得到一个适当的异常
p.S对于被定义为资源的图像,我也有同样的问题。因此,在删除第一个对话框时,仍然会发生这种情况(关闭对话框仍然不拥有资源)。
public class MyWindow: Window
{
public MyWindow()
{
SetResources();
}
private void SetResources()
{
DependencyObject dependencyObject;
object temp;
temp = this.TryFindResource("MyResourceKey");
if (temp != null)
{
if (temp is DependencyObject)
{
dependencyObject = (DependencyObject)temp;
if (!dependencyObject.CheckAccess())
{
dependencyObject.Dispatcher.BeginInvoke(new System.Action(() => { this.SetResources(); }));
}
else
{
this.SetValue(BackgroundProperty, temp);
}
}
}
}
}
this.SetValue(StyleProperty, temp)