Search for the lost CultureInfo

In the .NET world if we want to localize an application we usually make use of resources. We can create a resource (a dictionary of words) for every language and .NET would figure out which resource to load.

This way the application is translated to every language by just adding a resource file to the application.

The CultureInfo

The way .NET knows which resource to use is by looking at the CultureInfo stored in the current Thread, so .NET is looking at the following static property   Thread.CurrentThread.CurrentUICulture.

Before .NET Framework 4.6 the CultureInfo was not passed to child threads. This is a problem of windows itself because the CultureInfo is not a part of the thread. In .NET Framework 4.6 they changed the behavior so that the CultureInfo is passed to the child threads. Also they introduced the property  CultureInfo.DefaultThreadCurrentUICulture, this property is pretty self-explanatory, it controls the default CultureInfo for every new thread.

The async problem

When creating a WPF application and setting the CultureInfo to a specific culture at first it looks like it works as expected but after a sometime the CultureInfo is set back to the default value (in my case en-US). This only happens when we mark the method  OnStartup async.

This is the code used in the App.xaml.cs (the WPF startup file).

In the sample we first get a specific culture and then set it on the CurrentUICulture and on the  DefaultThreadCurrentUICulture, this should make sure that the resource used by .NET Framework is the resource for nl-NL. After setting the CultureInfo we call Show on the MainWindow. The MainWindow looks like this.

The only thing that the MainWindow does is log the CultureInfo of the current thread.

This is the log that is produces by the code.

You can see that after the line  [App] Culture nl-NL, the following lines tells us that the CultureInfo is now en-US. The line [App] is produced at the end of the OnStartup method.

The explanation

The strange sequence produced by the log is actually explainable. A part of the change in .NET Framework 4.6 is also a change in the behavior of Task/Async. The change in behavior is that the CultureInfo of a thread will be captured when thread is started and then restored afterwards. In this sample the method OnStartup is async so the CultureInfo will be captured at the start of the method, at that moment the CultureInfo is still the default value en-US and is restored at the end of the method. So regardless of what I do in the async method, it will always be restored to the previous value.

So in the end we have found the lost CultureInfo…….

Leave a Reply