定义整个应用程序域的文化

发布于 2024-09-18 16:17:45 字数 71 浏览 6 评论 0原文

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

I'm creating a windows service that runs multiple threads.
Can I set the culture of my entire appDomain, instead of setting it to each thread separately?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

指尖凝香 2024-09-25 16:17:45

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

For 4.5 default app domain cultures could be set via CultureInfo class:

请持续率性 2024-09-25 16:17:45

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

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

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

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


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


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

This is not possible. Threads get their default culture when Windows creates the thread, initialized from the system default locale as configured in Control Panel + Region and Language. The relevant Win32 API functions are Get/SetThreadLocale().

There is no mechanism in the CLR to imbue a thread with another default. A common scenario for a thread is to start life created by unmanaged code and run lots of that unmanaged code, occasionally making a callback into managed code. That managed code will run with the Thread.CurrentCulture set to the culture selected by the unmanaged code. Or the Windows default if the unmanaged code didn't call SetThreadLocale(). Having the CLR change it would cause undiagnosable failure in the unmanaged code.

Of course you can override it explicitly but that's difficult to get right. The subtle formatting errors are easy enough to see, it gets hard when you use, say, data structures that implicitly rely on the collating orders of string. A SortedList suddenly cannot find an element back in the list that is actually present. Controlling it is hard too, lots of little threadpool thread callbacks throughout the .NET framework.

Don't mess around with this to avoid falling into traps like these, either rely on the system default or apply the CultureInfo explicitly.


UPDATE: as noted by Thomas, a solution will be available in .NET 4.5, it has a new property for the CultureInfo class to set the appdomain's default culture. MSDN docs are here. The exact interaction with unmanaged threads that enter managed code isn't very clear from the documentation, be sure to check this if you ever allow native code to make callbacks, such as through pinvoke, Marshal.GetFunctionPointerForDelegate() or a COM object's event.


UPDATE2: this was changed again in .NET 4.6, culture now flows from one thread to another so the nastiest failure modes are taken care of. Read the details about it in the MSDN article for CultureInfo.CurrentCulture. You have to explicitly target 4.6 to get the benefit.

失眠症患者 2024-09-25 16:17:45

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

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

You could have a custom method that will fire threads and set culture automatically:

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

And when you need to start a new thread simply use this method:

StartThread(state => { /** Do some processing on a new thread **/ }, null);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文