在.Net中:保持CurrentCulture在新线程上的最佳方式?

PBe*_*ger 24 .net wpf culture multithreading c#-4.0

在.Net 4.0 WPF项目中,我们需要在主线程上的每个线程上保留相同的CurrentCulture.

鉴于,我们可以使用以下代码初始化新线程的文化:

  1. 将信息保存在变量(上下文)中

    context.CurrentCulture = Thread.CurrentThread.CurrentCulture;
    context.CurrentUICulture = Thread.CurrentThread.CurrentUICulture;
    
    Run Code Online (Sandbox Code Playgroud)
  2. 在新线程上,从保存的上下文初始化

    Thread.CurrentThread.CurrentCulture = context.CurrentCulture;
    Thread.CurrentThread.CurrentUICulture = context.CurrentUICulture;
    
    Run Code Online (Sandbox Code Playgroud)

但是在这个TPL时代,异步编程和lambda委托,它感觉不对.

是的,我们实际上可以在应用程序运行时改变文化,但这是另一个故事.

你知道我们应该初始化以保持跟踪的任何设置,属性或配置吗?

Han*_*ant 25

没有好办法,不惜一切代价避免这种情况.根本问题是文化不是Thread.ExecutionContext的一部分,它不会从一个线程流向另一个线程.这是一个无法解决的问题,culture是本机Windows线程的属性.它将始终初始化为在控制面板的"区域和语言"小程序中选择的系统区域性.

对文化进行临时的线程局部更改很好,试图将"过程"切换到另一种文化是一个你将要寻找几个月的bug的来源.字符串整理顺序是最糟糕的问题来源.


编辑:此问题已在.NET 4.5中使用CultureInfo.DefaultThreadCurrentCulture和DefaultThreadCurrentUICulture属性修复.


编辑:并在.NET 4.6中获得真正的解决方案,文化现在从一个线程流向另一个线程.有关详细信息,请查看CultureInfo.CurrentCulture的MSDN文章.请注意,描述与行为不完全匹配,需要进行测试.


The*_*Dag 5

我不明白为什么Passant先生会对此提出警告并同时说这对文化进行"临时""线程本地化"改变是好的.没有线程文化是真正的线程本地 - 它可以通过公共属性引用线程的任何东西,正如我们所见.如果可以在短时间内更改它,那么为什么不能长时间更改它呢?你在哪里越线,为什么?

我也不是真的理解OP的感觉,"编写代码来复制他想要复制的东西""没必要".您可能希望将此代码放在可以重用它的地方,但除此之外我真的没有看到代码的问题.在我的书中,它比我见过的任何lambda表达都更加直接和精彩,它可以很好地完成这项工作.为了它的花哨而编写花哨的代码至少不是我的风格.

你可以这样做:

// Program.cs
static CultureInfo culture, uiCulture;

[STAThread]
static public void Main()
{
   var t = Thread.CurrentThread;
   culture = t.CurrentCulture;
   uiCulture = t.CurrentUICulture;
}

static public Thread CreateThread() 
{
    return new Thread() { CurrentCulture = culture, CurrentUICulture = uiCulture }; }
}
Run Code Online (Sandbox Code Playgroud)