当前的文化信息(CurrentCulture和/或CurrentUICulture)是正在运行的线程的属性,这让我感到奇怪。至少看起来这样的事情的范围应该在过程层面上升一级。
但是一旦听到理由,这些事情通常都有意义。找出为什么.NET设计者认为Thread是放置这个属性的正确位置可能很有启发性。
答案 0 :(得分:10)
对于初学者来说,这不是他们真正的选择。这个决定在他们开始之前已经做了很长时间,文化是操作系统线程的属性。例如,查看Get / SetThreadLocale()API函数的SDK文档。
这并没有完全解释它,他们已经虚拟化了其他操作系统功能,虽然这个功能非常很难虚拟化,因为很多API都是文化敏感的,尤其是COM。
下一个很好的理由是因为在整个过程中改变文化是非常难以实施的。这是一个无法解决的竞争条件。其他一些线程可能正在格式化具有文化亲和力的数据。虽然锁可以防止它在更改时使用文化属性,但它可以不阻止它在格式化调用链的中间进行更改。它需要它们采取某种全局锁定并在格式化作业期间保持它。死锁很可能非常。
还有另外一个方面,我认为这是真正的问题。它与Thread.ExecutionContext属性有关。框架使用它将线程状态从一个线程“流”到另一个线程。非常模糊但很重要的是将安全上下文等内容灌输到工作线程上。如果上下文也可以灌输文化,那么你可以确定你开始的任何工人都拥有你所选择的文化,而不是操作系统的默认情况,这将是理想的。
没有,我真的不知道为什么。可能是因为我给出的第一个原因。然而,确实使改变线程的文化变得非常危险。可能导致的错误类型非常微妙。就像创建一个SortedDictionary,其中一个字符串作为主线程中的键,具有非操作系统默认文化。然后发现工作线程不能偶尔找回东西,因为字符串排序规则不同。
EDIT2:文化现在按照.NET 4.6第4段中的描述流动。这应该可以缓解所有问题。
答案 1 :(得分:6)
我会拍摄 - 也许是因为你需要使用不同文化的多个同时线程?如果你想到一个多语言的asp.net网站,你不希望这个过程与一种语言联系在一起......一个网络请求可能是EN-US和另一个fr-FR。
答案 2 :(得分:2)
窗口句柄本身是特定于线程的。您不应该在不同线程的上下文中使用窗口句柄(用于顶级窗口,子控件等),因为实现窗口处理(GDI)的代码本身不是线程安全的。由于UICulture是特定于窗口的,因此它意味着它也在线程级别定义。
其他GUI方面也是特定于线程的,例如活动窗口和焦点。虽然有一个API,但我记不起名称,它将来自不同线程的UI上下文连接在一起,以便在多个用户界面线程之间共享焦点,活动窗口。
答案 3 :(得分:2)
CurrentCulture只不过是对CultureInfo的引用,因此只要允许它挂在线程上(只有一个引用的内存)就不会丢失。同时,您可以让用户精确控制每个线程的当前文化 - 这在某些类型的应用程序中非常重要。
对于现代软件的非英语用户来说,使用这种细粒度的一个原因可能更为明显。我必须经常在Windows中切换键盘,并且能够通过一个全局键盘快捷键轻松完成。在线程上使用CultureInfo允许我们在.NET应用程序中轻松实现类似的逻辑,而无需在每个进程中更改该信息。
想到的用法示例:
我可能想要一个快捷方式,可以根据当前用户的请求在短时间内改变程序中的文化(许多应用程序需要允许同一工作站和同一会话中的多个用户)。但是同样的过程可能必须继续使用机器上的默认CultureInfo来例如记录始终具有相同的时间戳格式。
您可能还有一个报告解决方案,可以为全球公司的多个分支机构转储报告,每个分支机构都在自己的文化中。如果您可以更改每个线程的CultureInfo,那么您的设计将受到更少限制。
另一个原因是,如果您想要使用特定文化写入文件,但您不希望在写入函数中指定文化(例如,因为这些函数已经编写)。然后,您可以轻松地更改该逻辑,而无需在可能正在进行需要默认文化的工作的其他线程上更改它。