我有一个.NET MVC / WebApi应用程序,它在ASP.NET AcquireRequestState事件期间为当前线程设置Culture(我们使用自定义逻辑来确定每个用户的首选ui文化)。虽然这适用于同步情况,但我担心在使用异步或显式多线程或背景线程时(例如使用Task.Run())它将无法工作。
与Thread.CurrentPrincipal不同,它与逻辑控制流一起流动,文化似乎只是随着线程流动:
Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo(FigureOutUsersCulture());
Task.Run(() => Thread.CurrentThread.CurrentUICulture.Dump()); // en-US
为此类应用程序设置文化的最有效方法是什么?
注意:我对任何需要使用async / await或其他线程的开发人员记住初始化文化的答案感到兴奋。如果可能的话,我希望async / await能够提供强大的功能。如果这真的不可能,我当然也会接受这个答案。
编辑: 我知道如果你不在请求线程中等待任务,使用Task.Run()在ASP.NET中有问题。也就是说,我正在尝试编写基础设施,以尽可能最强大的方式进行设置。我不知道其他开发人员会做什么,所以如果我可以为它设置,我想成为。
修改: 关于发布的“可能重复”的说明。我同意这两个问题都是相关的,但它们不一样!一个人要求为整个应用程序设置一种文化,这与我正在尝试做的相反。另一个解决方案为MVC3风格的异步控制器设置文化,这是我想要完成的一小部分(对我而言,在很大程度上是不相关的)。
答案 0 :(得分:2)
Kyle关于将文化不变作业委托给其他线程(或在应用程序池中安排)的建议是明智的。如果工作确实需要了解文化,请将其作为参数传递。
简单地使用await
而没有像ConfigureAwait(false)
这样的花哨技巧会在延续中保留HttpContext和线程文化,所以我会使用*。我没有看到任何与AspNetSynchronizationContext相关的问题(https://stackoverflow.com/a/13494570/289992),你选择c#的原因是为了享受它的生产力优势。
*如果您正在编写库代码,可以考虑ConfigureAwait(false)
。您再次确保所有“正常环境”信息(Context.Current,CurrentUICulture等)作为参数传入。这里也有一些很好的技巧CultureAwaiter,也许你可以用它做点什么。也许你会想要阅读the costs并自己决定实施这些优化是否值得你花时间。
答案 1 :(得分:0)
考虑到“可能重复”的评论,我不确定是否有比EZI所说的更好的答案。如果你想创建一个新的线程,你需要告诉它有关文化。
更好的问题可能是为什么你需要其他线程的文化?让这些线程为你工作,然后当你回到主线程,你可以将信息转换为字符串或你有什么。这可能不合适,因为我不知道线程到底在做什么。