【问题标题】:How to set the value of main thread's CultureInfo.CurrentUICulture from a child thread in .NET Core 3.1?如何在 .NET Core 3.1 的子线程中设置主线程 CultureInfo.CurrentCulture 的值?
【发布时间】:2021-04-08 15:19:08
【问题描述】:

背景:

我有一个异步等待函数,它从外部源获取语言和区域设置参数,这将用于设置为 CurrentUICulture。

我的 Web 应用程序是使用 C# 在 .NET Core 3.1 中构建的

问题:

CurrentUICulture 仅在 Child 方法的上下文中设置,一旦超出此范围,CurrentUICulture 不会反映更改的值。

我的困境:

我知道总是建议从主线程(而不是从子线程)设置 CurrentUICulture 的值,但我正在处理一个对 Thread.CurrentThread.CurrentUICulture 和它有太多依赖的现有代码我几乎很难在各个地方改变。

片段:

public class Example
{
   public static async Task Main()
   {
      Console.WriteLine("Main Thread: Current UI culture is {0}",
                        Thread.CurrentThread.CurrentUICulture.Name);
     
      await Child();      

      Console.WriteLine("Main Thread: UI culture after change is {0}",
                        Thread.CurrentThread.CurrentUICulture.Name);
   }
   public static async Task Child()
   {
      //get the culture text from an external service (assume this will return "pt-BR")
      var cultureText = await externalService.GetCultureAsync();

      //set the culture
      Thread.CurrentThread.CurrentUICulture = new CultureInfo(cultureText);
      Console.WriteLine("Child Thread: UI culture changed to {0}",
                        Thread.CurrentThread.CurrentUICulture.Name);
   }
}

实际输出:

(假设外部服务返回的值为“pt-BR”[葡萄牙语巴西])

Main Thread: Current UI culture is en-US
Child Thread: UI culture changed to pt-BR
Main Thread: UI culture after change is en-US

期望的输出:

Main Thread: Current UI culture is en-US
Child Thread: UI culture changed to pt-BR
Main Thread: UI culture after change is pt-BR

任何解决问题的线索都将是非常可观的。

【问题讨论】:

  • 不要设置线程文化。将其显式传递给任何接受IFormatProvider 的格式化或解析方法。没有理由设置父线程文化或子线程文化本身
  • Task 操作Thread.CurrentThread 是一个坏主意,因为您无法保证Task 最终会在哪个线程上运行。这是针对局部问题的全局解决方案。如果您必须将代码固定到线程,因为它操纵文化,那么这样做,明确创建和管理Threads。这当然很尴尬,但这就是线程亲和性所带来的。
  • 为什么不让子任务将区域性字符串返回到主线程并让主线程设置区域性?
  • @HereticMonkey - 这不像你在我的 sn-p 中看到的那么简单。实际代码太复杂了。
  • 这个想法不仅糟糕,而且“不可行”。要么不使用Tasks,要么不使用Thread.CurrentCulture,这是基本要点。从理论上讲,可以使用自定义调度程序和自定义上下文以及随任务传递的自定义上下文来确保文化被捕获,但这些解决方案比修复代码工作量更大,而且最终肯定更难维护。请注意,线程之间没有“父”或“子”的概念;只有任务有类似的东西(即使在那里也很少使用)。

标签: c# async-await cultureinfo .net-core-3.1 currentuiculture


【解决方案1】:

我假设你不希望你的主线程在它的文化集之前做任何其他事情。这对我来说似乎是一个合理的假设。

在这种情况下,你可以阻塞主线程:

public static async Task Main()
{
  // Nothing should use await before this line.
  var cultureText = externalService.GetCultureAsync().GetAwaiter().GetResult();
  Thread.CurrentThread.CurrentUICulture = new CultureInfo(cultureText);

  // Other code that can use await.
}

如果这是一个 UI 应用,那么您可以在后台线程上运行异步代码:

public static async Task Main()
{
  // Nothing should use await before this line.
  var cultureText = Task.Run(() => externalService.GetCultureAsync()).GetAwaiter().GetResult();
  Thread.CurrentThread.CurrentUICulture = new CultureInfo(cultureText);

  // Other code that can use await.
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-31
    • 1970-01-01
    • 2010-12-19
    • 2020-08-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多