1

I am experiencing a problem at application startup from time to time on production machines. It doesn't happen every time the application starts, and apparently it only happens on reboot. The application is started from login, added to HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run.

Apparently, the problem is more frequent when resetting the machine, than during a reboot. Starting the application manually after it crashes is successful.

The following exception is thrown during startup:

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. at System.Windows.Threading.Dispatcher.VerifyAccess() at System.Windows.Style.Seal() at System.Windows.StyleHelper.UpdateStyleCache(FrameworkElement fe,FrameworkContentElement fce, Style oldStyle, Style newStyle, Style& styleCache) at System.Windows.FrameworkElement.OnStyleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) at System.Windows.DependencyObject.OnPropertyChanged(DependencyPropertyChangedEventArgs e) at System.Windows.FrameworkElement.OnPropertyChanged(DependencyPropertyChangedEventArgs e) at System.Windows.Controls.TextBlock.OnPropertyChanged(DependencyPropertyChangedEventArgs e) at System.Windows.DependencyObject.NotifyPropertyChange(DependencyPropertyChangedEventArgs args) at System.Windows.DependencyObject.UpdateEffectiveValue(EntryIndex entryIndex, DependencyProperty dp, PropertyMetadata metadata, EffectiveValueEntry oldEntry, EffectiveValueEntry& newEntry, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType operationType) at System.Windows.DependencyObject.InvalidateProperty(DependencyProperty dp) at System.Windows.FrameworkElement.UpdateStyleProperty() at System.Windows.FrameworkElement.OnInitialized(EventArgs e) at System.Windows.FrameworkElement.TryFireInitialized() at System.Windows.FrameworkElement.EndInit() at MS.Internal.Xaml.Runtime.ClrObjectRuntime.InitializationGuard(XamlType xamlType, Object obj, Boolean begin) --- End of inner exception stack trace --- at System.Windows.Markup.XamlReader.RewrapException(Exception e, IXamlLineInfo lineInfo, Uri baseUri) at System.Windows.Markup.WpfXamlLoader.Load(XamlReader xamlReader, IXamlObjectWriterFactory writerFactory, Boolean skipJournaledProperties, Object rootObject, XamlObjectWriterSettings settings, Uri baseUri) at System.Windows.Markup.WpfXamlLoader.LoadBaml(XamlReader xamlReader, Boolean skipJournaledProperties, Object rootObject, XamlAccessLevel accessLevel, Uri baseUri) at System.Windows.Markup.XamlReader.LoadBaml(Stream stream, ParserContext parserContext, Object parent, Boolean closeStream) at System.Windows.Application.LoadComponent(Object component, Uri resourceLocator) at Exception.Occurs.At.Different.Origins.Between.Startup()

As seen from the StackTrace, there is something going on while updating style cache. I haven't been able to reproduce this on my own computer. There are no threads involved here while starting the application, but there are a few AppDomains. The origin of the exception is not always the same, but it is exactly the same from Application.LoadComponent(Object component, Uri resourceLocator)

Because our application needs to find the configuration file from a different location than the executable (..\ProgramData....) depending on the OS, we use a separate AppDomain where we instruct it where to look for the configuration file, as we could not find any better solution of telling ConfigurationManager where to look for the file. It could of course, be related to this, though not necessarily. EDIT: ConfigurationManager.OpenMappedExeConfiguration Doesn't seem to work, as it won't refresh any user or application settings accessed through Properties.Settings.Default, etc.

Does anyone have any suggestions or recommendations on how to deal with this? Sorry I am not able to provide you with a sample to reproduce with.

bigfoot
  • 455
  • 5
  • 12
  • I haven't been able to work on this since posting the question, but will try out the solution posted at http://stackoverflow.com/questions/6150644/change-default-app-config-at-runtime/6151688#6151688 – bigfoot Dec 10 '12 at 08:56

3 Answers3

1

That exception was because you are modifying a visual element from a thread that is not the visual one. I know this because in the first line of your exception it said:

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.

All the rest of the exception doesn't matter. I think it is when you are loading the initial configuration, then you use other thread. The random behavior could be that some time you find the configuration before the TextBlock control is loaded, so this times the exception will no be thrown.

To solve this please take a look to this question, and the last answer that I give (the one that use the SynchronizationContext, that really works with WPF application that use several threads). If is not clear comment and I will write the solution here.

Hope this answer helps to find that random error, its are the worsts...

Community
  • 1
  • 1
Raúl Otaño
  • 4,640
  • 3
  • 31
  • 65
  • @Paul I don't explicitly load the configuration myself. We have made an startup shim to load the application "normaly" inside another appdomain. As far as I know, all the threads we have already use Dispatcher.BeginInvoke/Invoke to perform operations on the UI. The only thing I can think of here is that some operation is dispatched to the UI **before** the UI thread is created. Is that even possible? Also, this exception **only** occurs when executing after windows logon, but never on manual startup. – bigfoot Nov 23 '12 at 23:07
  • Be careful!, even if you are using Dispatcher.BeginInvoke, if you are updating the view from another thread, if you are not using a synchronization context, that exception will be raised. Maybe may also occur if you set a binding ,for example, that modify the view. Check this, maybe using a synchronization context for the load initial information could remove that exception. – Raúl Otaño Nov 26 '12 at 17:41
0

I'm not sure what is causing this exception but I there is a workaround to your problem.

Instead of creating a separate AppDomain just for loading a different configuration file, you could use ConfigurationManager.OpenMappedExeConfiguration which allows you to load any .config file from anywhere in your local file system.

You use it like this:

//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);

Use config.GetSection() to get specific sections for read-only use or directly the config object to change the configuration at run-time.

And you will not need the different AppDomain which will mean faster startup time :)

Panos Rontogiannis
  • 4,154
  • 1
  • 24
  • 29
  • I was not part of the initial research and implementation of the mapping of the configuration file, but I do believe the option you suggest was considered. The problem was that in this configuration returned by OpenMappedExeConfiguration is not loaded into the currently loaded configuration, and attempting to access these settings from Properties.Settings.Default to get user or application settings would not get data from the mapped configuration file. I need to check with the rest of the project just to make sure. – bigfoot Nov 23 '12 at 08:15
0

Getting rid of the extra AppDomain used to specify configuration file, and replacing it with the method specified in this link took care of the problem.

Community
  • 1
  • 1
bigfoot
  • 455
  • 5
  • 12