问题描述
我想为整个应用程序设置文化.我尝试了以下方法:
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);
它适用于当前线程,但是稍后我创建并启动一个后台工作线程.当我创建工作线程时,当前线程将通过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 the worker thread will run with my computer's culture.
有什么想法可以为整个应用程序树立文化吗?
Any ideas to set the culture for the whole application?
推荐答案
注意:过时的资料,请务必阅读底部的更新"以了解.NET 4.6中的更改
NOTE: dated material, be sure to read the Update at the bottom for changes in .NET 4.6
是的,这是一个常见的请求,但不可用. Windows始终将操作系统线程初始化为系统默认的LCID,该默认ID在控制面板"的区域和语言选项"小程序中配置.只要您自己创建线程,就可以覆盖它.但这对于线程池线程和可能由运行您的进程的某种非托管代码(例如COM服务器)创建的线程不切实际.
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.
后一种情况就是问题所在. .NET在由非托管代码创建的线程上运行托管代码没有问题.但是它对线程的初始化方式无能为力.对于CurrentUICulture来说确实如此,但对于诸如Thread.SetApartmentState()之类的更晦涩的东西也是如此.不要低估这种线程在您的程序中运行代码的可能性,由Microsoft编写的COM服务器对线程非常满意.
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.
您将必须使用细齿梳梳通您的代码,并找到可能在未创建的线程上运行的任何代码.任何事件处理程序都是可疑的,任何具有回调的BeginXxx()方法都是可疑的. BackgroundWorker绝对是较小的问题.
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.
不覆盖线程的区域性可能会产生非常且难以诊断的bugz.一个很好的例子是键入字符串的SortedList.当使用错误的区域性运行时,它将随机地找不到列表中实际存在的元素.原因是该列表不再在具有不同排序规则的其他区域性中进行排序.
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.
如果我设法吓到你了,那我就会明白我的意思了.这发生在我身上,调试了一个非常大的程序的问题,该程序在丹麦机器上表现异常.我们没有丹麦语本地化,因此强制UI以英语运行.一个工作线程使用一棵红黑树,该树以字符串为键.当被要求与Åårdvårks打交道时,它随机失败了.花了我一周的时间.
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.
更新:.NET 4.5中已解决此问题. CultureInfo类现在具有 DefaultThreadCurrentCulture 和DefaultThreadCurrentUICulture.设置后,它将用于初始化任何托管线程的区域性,而不是默认的Windows系统区域性.我还不清楚它如何与由本机代码启动并输入托管代码的线程交互.
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.
更新:.NET 4.6中此问题有更彻底的解决方案.文化现在会自动流动,这是理想的行为. CultureInfo的MSDN文章.CurrentCulture()对此进行了讨论.提供的信息仍然令人困惑,从实验上看,它似乎也流向Thread对象,而不仅仅是Task或线程池线程,并且未使用DefaultThreadCurrentCulture.建议前进两步,后退一步,进行测试.
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.
这篇关于C#BackgroundWorker的文化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!