为整个 appdomain 定义文化

Posted

技术标签:

【中文标题】为整个 appdomain 定义文化【英文标题】:Define culture for entire appdomain 【发布时间】:2010-09-13 07:45:42 【问题描述】:

我正在创建一个运行多个线程的 Windows 服务。 我可以设置整个 appDomain 的文化,而不是分别设置到每个线程吗?

【问题讨论】:

【参考方案1】:

对于 4.5 的默认应用程序域文化可以通过 CultureInfo 类设置:

DefaultThreadCurrentCulture DefaultThreadCurrentUICulture

【讨论】:

【参考方案2】:

这是不可能的。当 Windows 创建线程时,线程将获得它们的默认区域性,从控制面板 + 区域和语言中配置的系统默认区域设置初始化。相关的 Win32 API 函数是 Get/SetThreadLocale()。

CLR 中没有为线程注入另一个默认值的机制。线程的一个常见场景是启动由非托管代码创建的生命并运行大量非托管代码,偶尔会回调托管代码。该托管代码将在 Thread.CurrentCulture 设置为非托管代码选择的区域性的情况下运行。如果非托管代码没有调用 SetThreadLocale(),则为 Windows 默认值。更改 CLR 会导致非托管代码出现无法诊断的故障。

当然,您可以明确地覆盖它,但这很难做到。细微的格式错误很容易看到,当您使用隐式依赖于字符串排序顺序的数据结构时,就会变得很困难。 SortedList 突然无法在列表中找到实际存在的元素。控制它也很困难,整个 .NET 框架中有很多小线程池线程回调。

不要乱用它以避免陷入这样的陷阱,要么依赖系统默认值,要么显式应用 CultureInfo。


更新:正如 Thomas 所指出的,.NET 4.5 中将提供一个解决方案,它为 CultureInfo 类提供了一个新属性,用于设置 appdomain 的默认文化。 MSDN 文档are here。与进入托管代码的非托管线程的确切交互在文档中不是很清楚,如果您允许本机代码进行回调,请务必检查这一点,例如通过 pinvoke、Marshal.GetFunctionPointerForDelegate() 或 COM 对象的事件。


UPDATE2:这在 .NET 4.6 中再次更改,文化现在从一个线程流向另一个线程,因此处理了最恶劣的故障模式。在 CultureInfo.CurrentCulture 的 MSDN 文章中阅读有关它的详细信息。您必须明确定位到 4.6 才能获得好处。

【讨论】:

根据this page,在 .NET 4.5 中将有可能:“为应用程序域定义文化的能力”。但是我没有找到怎么做...我在 AppDomain 或 AppDomainSetup 中看不到任何相关属性【参考方案3】:

您可以有一个自定义方法来自动触发线程并设置区域性:

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

当你需要启动一个新线程时,只需使用这个方法:

StartThread(state =>  /** Do some processing on a new thread **/ , null);

【讨论】:

不错的解决方案......但它没有达到目标 - 我需要一些能够设置文化的东西,即使我忘记设置它。如果我忘记通过“StartThread”方法启动线程,也会发生同样的情况。我希望所有线程自动继承他们的文化

以上是关于为整个 appdomain 定义文化的主要内容,如果未能解决你的问题,请参考以下文章

C# - 从另一个 AppDomain 中的方法返回值

捕获当前线程中的所有异常

如何为整个 c# 应用程序设置默认文化信息

跨 AppDomain 的自定义序列化

自定义 AppDomain 和 PrivateBinPath

跨 AppDomain 传递自定义对象