c# winform CultureUICulture 意外恢复到以前的值

c# winform CultureUICulture reverting to previous value unexpectedly

我有一个基本的 Winform 应用程序 (.Net 4.6),其中主窗体仅包含一个停靠面板。该表单充当屏幕管理器,将通过 adding/removing 自定义用户控件 to/from 面板更改屏幕。

简单地说,我在处理屏幕中有一个按钮,如果您单击它,将触发一个简单的回调:

private void langButton_Click(object sender, EventArgs e)
{
      ActionCallback?.Invoke(UserAction.BackToTitle);
}

这将在主窗体中调用一个方法,最终:

System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo("en");

现在我检查了 CurrentUICulture 是否按预期更改,但是一旦它返回到调用行之后的 UserControl,CurrentUICulture 就会神奇地恢复原状在执行委托之前无论它曾经是什么! (没有其他代码改变文化)

更令人困惑的是我的标题屏幕的类似代码工作正常。 他们都 运行 在 UI 线程上。

我一直在网上搜索,也尝试了很多方法,包括锁定正在改变文化的行,以防值被缓存或发生其他事情但没有运气。

显然省略了很多代码,但这就是它的要点。我可以故意将文化传回并再次分配它,但那会很糟糕。

任何人都可以阐明这种行为并可能提出一些解决方案吗?

编辑 1:

我想我终于找到了问题所在。回调是这样的:

    private async void HandleUserAction(UserAction action)
            {
                switch (action)
                {
                    case UserAction.BackToTitle:
                        System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo("en");
                       break;
                   //other cases omitted
                }
            }

我基本上做了一个快速测试并将其提取到另一个匿名函数但没有异步:

screen.ActionCallback2 += (a) => { System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo("en");};

终于成功了!

我不确定它是否与下面的 post 重复,因为我已经在使用 .Net 4.6 或更高版本,但我必须做更多的阅读。

我不会回答我自己的问题,因为我仍在努力理解为什么会发生这种情况,如果其他人可以解释这一点,请随时这样做。

编辑 2:

我发现这个问题可以用下面的代码重现

    private async void button16_Click(object sender, EventArgs e)
    {
            //will revert back to previous value once it exits the function
        System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo("jp");
    
    }
            
    private void button15_Click(object sender, EventArgs e)
    {
                //it will be changed to jp
         System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo("jp");
         Task.Run(() =>
         {
            this.Invoke((MethodInvoker)delegate
            {
                    //this will be changed back to jp after exiting the thread, even though its same UI thread
                  System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo("en");
            });
         });
     }

最后我通过将它添加到我的 app.config

来修复它
<AppContextSwitchOverrides value="Switch.System.Globalization.NoAsyncCurrentCulture=true" />

虽然对我来说还是有点陌生​​,尤其是当函数 button15_Click 不涉及异步时。