C#BackgroundWorker的文化

时间:2010-03-05 10:18:51

标签: c# multithreading culture

我想为我的整个应用程序设置文化。我尝试了以下方法:

Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(wantedCulture);
Thread.CurrentThread.CurrentUICulture = CultureInfo.CreateSpecificCulture(wantedCulture);
Application.CurrentCulture = CultureInfo.CreateSpecificCulture(wantedCulture);

它适用于当前线程,但稍后我创建并启动后台工作线程。当我创建worker时,当前线程使用wantedCulture执行,但工作线程将使用我的计算机文化运行。

为整个应用程序设置文化的任何想法?

6 个答案:

答案 0 :(得分:35)

注意:注明日期的材料,请务必阅读底部的更新以了解.NET 4.6中的更改

是的,这是一个常见的请求,但它不可用。 Windows始终将OS线程初始化为系统默认LCID,在“控制面板”的“区域和语言选项”小程序中进行配置。只要您自己创建线程,就可以覆盖它。但是,对于线程池线程和线程来说,这可能是由运行您的进程的某种非托管代码(如COM服务器)创建的。

后一种情况是问题所在。 .NET在由非托管代码创建的线程上运行托管代码没有问题。但它无法对线程初始化的方式做任何事情。这对于CurrentUICulture来说也是如此,但对于像Thread.SetApartmentState()这样更加模糊的东西也是如此。不要低估这样一个线程在你的程序中运行代码的可能性,微软编写的COM服务器非常高兴。

您必须使用细齿梳子填写代码,并找到可能在您未创建的线程上运行的任何代码。任何事件处理程序都是可疑的,任何具有回调的BeginXxx()方法都是如此。 BackgroundWorker肯定是较小的问题。

不覆盖线程的文化可以产生非常微妙且难以诊断的bugz。一个很好的例子是一个键入字符串的SortedList。当使用错误的文化运行时,它将无法找到列表中实际存在的元素。由于列表不再在具有不同整理规则的另一种文化中进行排序而导致。

如果我设法吓到你,那么我就会传达我的信息。这件事发生在我身上,用一个在丹麦机器上行为不端的大型程序调试问题。我们没有丹麦语本地化,并迫使用户界面以英语运行。工作线程使用了一个以字符串为键的红黑树。当被要求与Åårdvårks打交道时,它失败了。花了我一个星期。


更新:此问题已在.NET 4.5中得到解决。 CultureInfo类现在有DefaultThreadCurrentCulture和DefaultThreadCurrentUICulture。设置后,它将用于初始化任何托管线程的文化,而不是默认的Windows系统文化。究竟它是如何与本机代码启动并进入托管代码的线程交互的,我还不清楚。


更新:此问题在.NET 4.6中有更彻底的解决方案。文化现在自动流动,是理想的行为。 CultureInfo.CurrentCulture()的MSDN文章讨论了它。提供的信息仍然令人困惑,实验上它似乎也流向Thread对象,而不仅仅是Task或线程池线程,并且不使用DefaultThreadCurrentCulture。前进两步,后退一步,建议进行测试。

答案 1 :(得分:1)

我的解决方案是拥有一个中心文化属性(Application.CurrentCulture是每个线程)并在工作线程的开头设置当前线程文化。作业系统可以帮助解决这个问题,因为您可以轻松地在工作项之前和之后执行通用代码,并且作业系统类可以保持文档可以通过其作业访问,因此您不需要全局变量。

答案 2 :(得分:1)

简单地说; 不要这样做

不要在主线程(Thread.CurrentThread)之外的任何其他线程上执行任何特定于文化的格式化。在其他线程上获得正确的文化 - 创建其他所有线程 - 只是一种痛苦,迟早会忘记正确设置它。最好只是避免共同的痛苦,只在你保证在正确的文化设置上的线程上进行文化特定的格式化,转换等。

答案 3 :(得分:0)

您不能为每个新创建的线程执行此操作。你应该手工完成(但我不认为为线程池线程设置文化是一个好主意!)。也许你的应用程序应该依赖于Application.CurrentCulture或其他一些全局的东西..

答案 4 :(得分:0)

  

Windows始终将OS线程初始化为系统默认LCID,   在Control中的区域和语言选项小程序中配置   面板。

不幸的是,我不得不反对这一点,并且发现了相反的结果。

系统安装为美国英语。 去控制面板将所有内容更改为丹麦文并复制到所有帐户。 重新启动。

运行控制台应用程序以丹麦语运行。 运行web应用程序问浏览器它说丹麦语。 从网络应用程序启动线程,它是作为美国而非丹麦推出的,我无法弄清楚原因。

答案 5 :(得分:0)

我知道这个话题很老但我发现自己处于一个与OS文化相关的线索中。问题

我解决了这个问题:因为BackgroundWorker在UserControl中(如果它在Form中就有效等等......)我在构造时在UserControl(或Form)中设置了一个字段。在DoWork事件处理程序中,我在我的操作中使用此字段。代码如下:

    /// <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);
    }