如何在启动事件中的 WPF 中设置 CultureInfo?



我有一个用于 .NET 4.7.2 的 WPF 应用程序,并希望基于命令行参数设置全局区域性。根据许多来源(例如这里或官方文档(,多线程应用程序中的区域性是使用CultureInfo.DefaultThreadCurrentCulture设置的。这在应用程序的构造函数中确实有效。但是,它在我需要的地方不起作用,即在Application_Startup事件中,我可以在其中评估命令行参数。为什么会这样,我该如何解决?

App.xaml:

<Application x:Class="WpfApp1.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApp1"
StartupUri="MainWindow.xaml"
Startup="Application_Startup">
<Application.Resources>
</Application.Resources>
</Application>

App.xaml.cs:

namespace WpfApp1
{
public partial class App : Application
{
public App()
{
Demo("en-EN");
}
// Stops working if Demo is called in Application_Startup instead of constructor
/* private void Application_Startup(object sender, StartupEventArgs e)
{
// TODO Take culture code from StartupEventArgs
Demo("en-EN");
}
*/
private static void Demo(string cultureCode)
{
WriteDate();
SetCulture(cultureCode);
Task.Factory.StartNew(WriteDate);
}
private static void SetCulture(string code)
{
var ci = new CultureInfo(code);
CultureInfo.DefaultThreadCurrentCulture = ci;
CultureInfo.DefaultThreadCurrentUICulture = ci;
}
static void WriteDate()
{
var threadId = Thread.CurrentThread.ManagedThreadId;
var threadCulture = Thread.CurrentThread.CurrentCulture;
System.Diagnostics.Debug.WriteLine($"Thread {threadId} with culture {threadCulture} => {DateTime.Now}");
}
}
}

我的系统文化是德语。使用构造函数时的输出符合预期:

Thread 1 with culture de-DE => 09.01.2020 16:13:20
Thread 3 with culture en-EN => 1/9/2020 4:13:20 PM

现在,当我将对 Demo 的调用移动到 Application_Startup 事件时,输出为:

Thread 1 with culture de-DE => 09.01.2020 16:16:10
Thread 3 with culture de-DE => 09.01.2020 16:16:10

对 CultureInfo.DefaultThreadCurrentCulture 的调用没有得到尊重!有趣的是,如果我将此调用更改为 Thread.CurrentThread.CurrentCulture,这将解决问题。但是,我想为所有线程设置区域性,而不仅仅是当前线程。

您可以定义一个自定义入口点并从那里获取参数:

public class Program
{
static void Main(string[] args)
{
App app = new App(args);
app.InitializeComponent();
app.Run();
}
}
public partial class App : Application
{
public App(string[] args)
{
Demo("en-EN");
}
private static void Demo(string cultureCode)
{
WriteDate();
SetCulture(cultureCode);
for (int i = 0; i < 100; i++)
Task.Run((Action)WriteDate);
}
private static void SetCulture(string code)
{
var ci = new CultureInfo(code);
CultureInfo.DefaultThreadCurrentCulture = ci;
}
static void WriteDate()
{
var threadId = Thread.CurrentThread.ManagedThreadId;
var threadCulture = Thread.CurrentThread.CurrentCulture;
System.Diagnostics.Debug.WriteLine($"Thread {threadId} with culture {threadCulture} => {DateTime.Now}");
}
}

请记住将App.xamlBuild Action更改为Page,以防止编译器为您生成Main方法。

很难回答原因是什么,但查看线程窗口,我想线程池处理后台任务是在触发事件Application_Startup之前创建的。 您可以在应用构造函数中看到 1 个线程,在启动事件中看到 3 个线程。其中很可能有 1 个用于处理任务。

我看到 2 种可能的解决方案:

1(在应用程序构造函数中,您还可以使用环境访问命令行参数,因此只需将逻辑保留在构造函数中:

Environment.GetCommandLineArgs()

2( 为所有线程设置它 - 在Application_Startup中枚举它们并为所有线程设置区域性 使用此堆栈溢出答案

相关内容

  • 没有找到相关文章

最新更新