注意:过时的材料,请务必阅读底部的更新以了解 .NET 4.6 中的更改
是的,这是一个常见的请求,但它不可用。Windows 始终将操作系统线程初始化为系统默认 LCID,在控制面板的区域和语言选项小程序中配置。只要您自己创建线程,您就可以覆盖它。但这对于线程池线程和可能由运行您的进程的某种非托管代码(如 COM 服务器)创建的线程是不切实际的。
后一种情况是问题所在。.NET 在由非托管代码创建的线程上运行托管代码没有任何问题。但它不能对线程的初始化方式做任何事情。这对于 CurrentUICulture 是正确的,但对于像 Thread.SetApartmentState() 这样的更晦涩的东西也是如此。不要低估这样一个线程在您的程序中运行代码的可能性,微软编写的 COM 服务器非常适合线程。
您将不得不用细齿梳理您的代码,并找到可能在您未创建的线程上运行的任何代码。任何事件处理程序都是可疑的,任何具有回调的 BeginXxx() 方法也是如此。BackgroundWorker 绝对是较小的问题。
不覆盖线程的文化会产生非常微妙且难以诊断的错误。一个很好的例子是一个以字符串为键的 SortedList。当使用错误的区域性运行时,它会随机无法找到列表中实际存在的元素。由于列表不再在具有不同排序规则的另一种文化中排序。
如果我成功地吓到了你,那么我的信息就会传达出去。这发生在我身上,调试一个在丹麦机器上运行异常的非常大的程序的问题。我们没有丹麦语本地化,并强制 UI 以英语运行。工作线程使用以字符串为键的红黑树。当被要求与 Åårdvårks 打交道时,它随机失败了。花了我一个星期。
更新:此问题已在 .NET 4.5 中得到解决。CultureInfo 类现在具有DefaultThreadCurrentCulture和 DefaultThreadCurrentUICulture。设置后,它将用于初始化任何托管线程的文化而不是默认的 Windows 系统文化。我还不清楚它如何与由本机代码启动并输入托管代码的线程进行交互。
更新:这个问题在 .NET 4.6 中有更彻底的解决方案。文化现在自动流动,理想的行为。CultureInfo.CurrentCulture()的 MSDN 文章讨论了它。提供的信息仍然令人困惑,实验上它似乎也流向了一个线程对象,而不仅仅是一个任务或线程池线程,并且没有使用 DefaultThreadCurrentCulture。前进两步,后退一步,建议测试。