Define culture for entire appdomain
Asked Answered
M

3

7

I'm creating a windows service that runs multiple threads. Can I set the culture of my entire appDomain, instead of setting it to each thread separately?

Masterson answered 13/9, 2010 at 7:45 Comment(0)
H
8

This is not possible. Threads get their default culture when Windows creates the thread, initialized from the system default locale as configured in Control Panel + Region and Language. The relevant Win32 API functions are Get/SetThreadLocale().

There is no mechanism in the CLR to imbue a thread with another default. A common scenario for a thread is to start life created by unmanaged code and run lots of that unmanaged code, occasionally making a callback into managed code. That managed code will run with the Thread.CurrentCulture set to the culture selected by the unmanaged code. Or the Windows default if the unmanaged code didn't call SetThreadLocale(). Having the CLR change it would cause undiagnosable failure in the unmanaged code.

Of course you can override it explicitly but that's difficult to get right. The subtle formatting errors are easy enough to see, it gets hard when you use, say, data structures that implicitly rely on the collating orders of string. A SortedList suddenly cannot find an element back in the list that is actually present. Controlling it is hard too, lots of little threadpool thread callbacks throughout the .NET framework.

Don't mess around with this to avoid falling into traps like these, either rely on the system default or apply the CultureInfo explicitly.


UPDATE: as noted by Thomas, a solution will be available in .NET 4.5, it has a new property for the CultureInfo class to set the appdomain's default culture. MSDN docs are here. The exact interaction with unmanaged threads that enter managed code isn't very clear from the documentation, be sure to check this if you ever allow native code to make callbacks, such as through pinvoke, Marshal.GetFunctionPointerForDelegate() or a COM object's event.


UPDATE2: this was changed again in .NET 4.6, culture now flows from one thread to another so the nastiest failure modes are taken care of. Read the details about it in the MSDN article for CultureInfo.CurrentCulture. You have to explicitly target 4.6 to get the benefit.

Highness answered 13/9, 2010 at 9:58 Comment(1)
According to this page, it will be possible in .NET 4.5: "Ability to define the culture for an application domain". However I didn't find how to do it... I can't see any relevant property in AppDomain or AppDomainSetupCutout
A
17

For 4.5 default app domain cultures could be set via CultureInfo class:

Aurelioaurelius answered 6/11, 2011 at 20:57 Comment(0)
H
8

This is not possible. Threads get their default culture when Windows creates the thread, initialized from the system default locale as configured in Control Panel + Region and Language. The relevant Win32 API functions are Get/SetThreadLocale().

There is no mechanism in the CLR to imbue a thread with another default. A common scenario for a thread is to start life created by unmanaged code and run lots of that unmanaged code, occasionally making a callback into managed code. That managed code will run with the Thread.CurrentCulture set to the culture selected by the unmanaged code. Or the Windows default if the unmanaged code didn't call SetThreadLocale(). Having the CLR change it would cause undiagnosable failure in the unmanaged code.

Of course you can override it explicitly but that's difficult to get right. The subtle formatting errors are easy enough to see, it gets hard when you use, say, data structures that implicitly rely on the collating orders of string. A SortedList suddenly cannot find an element back in the list that is actually present. Controlling it is hard too, lots of little threadpool thread callbacks throughout the .NET framework.

Don't mess around with this to avoid falling into traps like these, either rely on the system default or apply the CultureInfo explicitly.


UPDATE: as noted by Thomas, a solution will be available in .NET 4.5, it has a new property for the CultureInfo class to set the appdomain's default culture. MSDN docs are here. The exact interaction with unmanaged threads that enter managed code isn't very clear from the documentation, be sure to check this if you ever allow native code to make callbacks, such as through pinvoke, Marshal.GetFunctionPointerForDelegate() or a COM object's event.


UPDATE2: this was changed again in .NET 4.6, culture now flows from one thread to another so the nastiest failure modes are taken care of. Read the details about it in the MSDN article for CultureInfo.CurrentCulture. You have to explicitly target 4.6 to get the benefit.

Highness answered 13/9, 2010 at 9:58 Comment(1)
According to this page, it will be possible in .NET 4.5: "Ability to define the culture for an application domain". However I didn't find how to do it... I can't see any relevant property in AppDomain or AppDomainSetupCutout
A
3

You could have a custom method that will fire threads and set culture automatically:

static bool StartThread(WaitCallback callback, object state)
{
    return ThreadPool.QueueUserWorkItem(s =>
    {
        // Set the culture
        Thread.CurrentThread.CurrentCulture = new CultureInfo("es-ES");
        // invoke the callback
        callback(s);
    }, state);
}

And when you need to start a new thread simply use this method:

StartThread(state => { /** Do some processing on a new thread **/ }, null);
Alidaalidade answered 13/9, 2010 at 8:1 Comment(1)
Nice solution... but it miss the target - I need something that will set the culture even when I forget to set it. The same can happen here if I forget to start the thread through the 'StartThread' method. I want all the threads to inherit their culture automaticallyMasterson

© 2022 - 2024 — McMap. All rights reserved.