C# BackgroundWorker's culture
I woudl like to set the culture for my whole application. I tried the following :
Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(wantedCulture);
Thread.CurrentThread.CurrentUICulture = CultureInfo.CreateSpecificCulture(wantedCulture);
Application.CurrentCulture = CultureInfo.CreateSpecificCulture(wantedCulture);
It works for the current thread, but later on I create and start a background worker thread. When I create the worker, the current thread executes with the wantedCulture but t开发者_开发技巧he worker thread will run with my computer's culture.
Any ideas to set the culture for the whole application?
NOTE: dated material, be sure to read the Update at the bottom for changes in .NET 4.6
Yes, this is a common request but it is not available. Windows always initializes an OS thread to the system default LCID, configured in the Regional and Language Options applet in Control Panel. You can override this as long as you create the threads yourself. But that is not practical for threadpool threads and threads that might have been created by some kind of unmanaged code running your process, like a COM server.
The latter case is the problem. .NET has no trouble running managed code on threads that were created by unmanaged code. But it cannot do anything about the way the thread is initialized. That's true for CurrentUICulture but also for more obscure stuff like Thread.SetApartmentState(). Don't underestimate the likelihood that such a thread runs code in your program, COM servers written by Microsoft are very thread-happy.
You will have to pour through your code with a fine-toothed comb and find any code that might run on a thread you didn't create. Any event handler is suspect, as is any BeginXxx() method that has a callback. BackgroundWorker is definitely the lesser problem.
Not overriding the thread's culture can produce very subtle and hard to diagnose bugz. A good example would be a SortedList that keys on a string. When run with the wrong culture, it randomly will fail to find elements that are actually present in the list. Caused by the list not being sorted anymore in another culture with different collation rules.
If I managed to scare you enough then I got my message across. This happened to me, debugging an issue with a very large program that misbehaved on a Danish machine. We didn't have a Danish localization and forced the UI to run in English. A worker thread used a red-black tree that had a string as the key. It failed randomly when asked to deal with Åårdvårks. Took me a week.
Update: this problem has been addressed in .NET 4.5. The CultureInfo class now has a DefaultThreadCurrentCulture and DefaultThreadCurrentUICulture. When set, it will be used to initialize the culture of any managed thread instead of the default Windows system culture. Exactly how it interacts with threads that got started by native code and enter managed code isn't yet clear to me.
Update: this problem had a more thorough solution in .NET 4.6. Culture now flows automatically, the ideal behavior. The MSDN article for CultureInfo.CurrentCulture() talks about it. The provided info is as yet confusing, experimentally it also appears to flow to a Thread object and not just a Task or threadpool thread and DefaultThreadCurrentCulture is not used. Two steps forward, one step back, testing is recommended.
My solution was to have a central culture property (Application.CurrentCulture is per-thread) and set the current thread culture to this in the beginning of a worker thread. A job system helps with this, since you can then easily execute generic code before and after the work item, and the job system class can hold the culture accessible by its jobs, so you don't need globals.
Simply put; Don't do it.
Don't do any culture specific formatting on any other thread than the main thread (Thread.CurrentThread
). Getting the correct culture on other threads - every other thread created - is just a pain and sooner or later you will forget to set it correctly. Better to just avoid the pain all together and only do culture specific formatting, converting, etc, on the thread that you're guaranteed to be on the correct culture settings.
You can't do this for every newly created thread. You should do it by hand (but I don't think that seting culture for thread pool threads is a good idea!). Maybe your application should depends on Application.CurrentCulture or some other global stuff..
Windows always initializes an OS thread to the system default LCID, configured in the Regional and Language Options applet in Control Panel.
Unfortunately I have to disagree with this and have found the opposite.
System was installed as US English. Went to control panel changed everything to Danish and copied to all accounts. Rebooted.
Run console app it runs in danish. Run web app ask browser it says danish. Launch thread from web app and it's launched as US not danish and I can't figure out why.
I know the topic is old but I found myself in a "thread with OS culture" problem.
I solved it so: as the BackgroundWorker is in a UserControl (it would be valid if it is in a Form and so on...) I set a field in the UserControl (or Form) when it is constructed. In the DoWork event handler I use this field in my operations. Here the code:
/// <summary>
/// Culture in which the GUI creates the control.
/// </summary>
private readonly CultureInfo _currentCulture;
/// <summary>
/// Default constructor.
/// </summary>
public MyControl()
{
InitializeComponent();
_currentCulture = CultureInfo.CurrentUICulture;
}
private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
ExampleClass.DoCultureDependentOperation(_currentCulture);
}
精彩评论