首页 文章

应用程序启动时出现随机InvalidOperationException

提问于
浏览
1

我在 生产环境 机器上不时在应用程序启动时遇到问题 . 它不会在每次应用程序启动时发生,显然它只在重新启动时发生 . 该应用程序从登录启动,添加到HKLM \ SOFTWARE \ Microsoft \ Windows \ CurrentVersion \ Run .

显然,重置机器时问题比重启时更频繁 . 崩溃后手动启动应用程序成功 .

启动期间抛出以下异常:

'System.Windows.Controls.TextBlock'的初始化引发了异常 . System.Windows.Markup.XamlParseException:'System.Windows.Controls.TextBlock'的初始化引发了异常 . ---> System.InvalidOperationException:调用线程无法访问此对象,因为另一个线程拥有它 . 在System.Windows.Threading.Dispatcher.VerifyAccess()在System.Windows.Style.Seal()在System.Windows.StyleHelper.UpdateStyleCache(FrameworkElement的FE,FrameworkContentElement上FCE,风格旧式,样式newStyle,样式和styleCache)在System.Windows .FrameworkElement.OnStyleChanged(DependencyObject的d,DependencyPropertyChangedEventArgs e)上System.Windows.DependencyObject.OnPropertyChanged(DependencyPropertyChangedEventArgs e)上System.Windows.FrameworkElement.OnPropertyChanged(DependencyPropertyChangedEventArgs e)上System.Windows.Controls.TextBlock.OnPropertyChanged(DependencyPropertyChangedEventArgs e)上System.Windows.DependencyObject.UpdateEffectiveValue(EntryIndex entryIndex,DependencyProperty dp,PropertyMetadata metadata,EffectiveValueEntry oldEntry,EffectiveValueEntry&newEntry,Boolean coerceWithDeferredReference,Boolean coerceWithCurrentValue,OperationType operationType)中的System.Windows.DependencyObject.NotifyPropertyChange(DependencyPropertyChangedEventArgs args)在System.Windows.DependencyObject.InvalidateProperty(的DependencyProperty DP)在System.Windows.FrameworkElement.UpdateStyleProperty()在System.Windows.FrameworkElement.OnInitialized(EventArgs e)上System.Windows.FrameworkElement.TryFireInitialized()在System.Windows.FrameworkElement .EndInit()在MS.Internal.Xaml.Runtime.ClrObjectRuntime.InitializationGuard(xamlType xamlType,对象OBJ,布尔开始)---内部异常堆栈跟踪的末尾在System.Windows.Markup.XamlReader.RewrapException(例外e,IXamlLineInfo lineInfo,Uri baseUri)在System.Windows.Markup.WpfXamlLoader.LoadBaml(XamlReader xamlReader)的System.Windows.Markup.WpfXamlLoader.Load(XamlReader xamlReader,IXamlObjectWriterFactory writerFactory,Boolean skipJournaledProperties,Object rootObject,XamlObjectWriterSettings设置,Uri baseUri)中,布尔值skipJournaledProperties,Object rootObject,XamlAccessLevel accessLevel,Uri baseUri)在System.Windows.Markup.XamlReader.LoadBaml(Stream stream,ParserContext p)位于Exception.Occurs.At.Different.Origins.Between.Startup()的System.Windows.Application.LoadComponent(Object component,Uri resourceLocator)中的arserContext,Object parent,Boolean closeStream)

从StackTrace可以看出,在更新样式缓存时会发生一些事情 . 我无法在自己的计算机上重现这一点 . 启动应用程序时,此处不涉及任何线程,但有一些AppDomains . 异常的起源并不总是相同,但它与Application.LoadComponent(对象组件,Uri resourceLocator)完全相同 .

因为我们的应用程序需要从可执行文件(.. \ ProgramData ....)以外的地方查找配置文件,具体取决于操作系统,我们使用单独的AppDomain,我们在其中指示查找配置文件的位置,因为我们找不到任何更好的解决方案,告诉ConfigurationManager在哪里查找文件 . 它当然可以与此相关,但不一定如此 . 编辑:ConfigurationManager.OpenMappedExeConfiguration似乎不起作用,因为它不会刷新通过Properties.Settings.Default等访问的任何用户或应用程序设置 .

有没有人对如何处理这个有任何建议或建议?对不起,我无法为您提供重现的样本 .

3 回答

  • 1

    该异常是因为您正在从不是可视线程的线程修改可视元素 . 我知道这是因为在你的例外的第一行它说:

    Initialization of 'System.Windows.Controls.TextBlock' threw an exception. System.Windows.Markup.XamlParseException: Initialization of 'System.Windows.Controls.TextBlock' threw an exception. ---> System.InvalidOperationException: The calling thread cannot access this object because a different thread owns it.

    所有其余的例外并不重要 . 我想是在加载初始配置时然后你使用其他线程 . 随机行为可能是有时在加载 TextBlock 控件之前找到配置,所以这次不会抛出异常 .

    要解决这个问题,请查看this问题,以及我给出的最后一个答案(使用 SynchronizationContext 的答案,它真正适用于使用多个线程的WPF应用程序) . 如果不清楚评论,我会在这里写出解决方案 .

    希望这个答案有助于找到随机错误,它是令人讨厌的......

  • 0

    我不确定是什么导致了这个异常但是我有一个解决方法来解决你的问题 .

    您可以使用ConfigurationManager.OpenMappedExeConfiguration而不是创建单独的 AppDomain 来加载不同的配置文件,它允许您从本地文件系统的任何位置加载任何.config文件 .

    你这样使用它:

    //Map the new configuration file.
    var configFileMap = new ExeConfigurationFileMap() { ExeConfigFilename = @"c:\myOther.config"};
    
    //Get the mapped configuration file
    System.Configuration.Configuration config = ConfigurationManager.OpenMappedExeConfiguration(configFileMap, ConfigurationUserLevel.None);
    

    使用 config.GetSection() 获取特定部分以供只读使用,或直接使用 config 对象在运行时更改配置 .

    而且你不需要不同的AppDomain,这意味着更快的启动时间:)

  • 0

    摆脱用于指定配置文件的额外AppDomain,并将其替换为this link中指定的方法,可以解决问题 .

相关问题