保持 CurrentCulture 处于异步/等待状态 [英] Keep CurrentCulture in async/await

查看:23
本文介绍了保持 CurrentCulture 处于异步/等待状态的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下伪代码

string GetData()
{
  var steps = new List<Task<string>>
  {
    DoSomeStep(),
    DoSomeStep2()
  };

  await Task.WhenAll(steps);

  return SomeResourceManagerProxy.RetrieveValuesForLocalizedStrings( steps.Select(s => s.Result) );

}

这个方法是从WebService调用的,我根据用户的浏览器设置设置了Thread.CurrentUICulture.

This method is called from WebService, where I set Thread.CurrentUICulture according to user's browser settings.

等待后,CurrentUICulture 丢失了(我在不同的线程上运行).

After await, the CurrentUICulture is lost (I run on different thread).

我已经解决了以下问题:

I have solved the issue with following:

    public class MyAwaiter<T> : INotifyCompletion
    {
        private TaskAwaiter<T> waiter;
        private CultureInfo culture;

        public MyAwaiter(TaskAwaiter<T> waiter)
        {
            this.waiter = waiter;
        }

        public PreserveCultureAwaiter<T> GetAwaiter() { return this; }

        public bool IsCompleted { get { return waiter.IsCompleted; } }

        public void OnCompleted(Action continuation)
        {
            culture = Thread.CurrentThread.CurrentUICulture;
            waiter.OnCompleted(continuation);
        }

        public T GetResult()
        {
            Thread.CurrentThread.CurrentUICulture = culture;
            return waiter.GetResult();
        }
    }

    public static MyAwaiter<T> KeepCulture<T>(this Task<T> task)
    {
        return new MyAwaiter<T>(task.GetAwaiter());
    }

...

    await Task.WhenAll(steps).KeepCulture();

这有一个缺点 - 需要记住对每个正在等待的任务调用 KeepCulture().(我也有一些扩展方法来保持 UI 文化在任务中).

This has one drawback - need for remembering to call KeepCulture() on every task that is being awaited. (I have also some extension method to keep the UI culture in task).

有没有更简单的方法来保护 UI 文化?

Is there any easier way how to preserve UI culture?

推荐答案

文化在 .NET Framework 中无法流动,这是一个非常臭名昭著的问题.在 Windows 上很难解决,文化是一个 线程的非托管属性,因此 CLR 无法确保它始终正确设置.这使得在主线程上修改 CurrentCulture 成为一个大错误.你得到的错误很难诊断.就像您在一个线程上创建的 SortedList 一样,该线程突然不再在另一个线程上排序.糟糕.

Culture does not flow in the .NET Framework, a very notorious problem. It is very hard to solve on Windows, culture is an unmanaged property of a thread so the CLR can't ensure it is always set correctly. That makes tinkering with the CurrentCulture on the main thread a big fat mistake. The bugs you get are very hard to diagnose. Like a SortedList you create on one thread that suddenly isn't sorted anymore on another. Yuck.

微软在 .NET 4.5 中做了一些事情,他们添加了 CultureInfo.DefaultThreadCurrentCulture 属性.还有 DefaultThreadCurrentUICulture.这仍然不能保证它会被正确设置,您调用的非托管代码可以更改它,而 CLR 对此无能为力.换句话说,错误将更难诊断.但至少你有一些想法什么时候可能会改变.

Microsoft did something about it in .NET 4.5, they added the CultureInfo.DefaultThreadCurrentCulture property. Also DefaultThreadCurrentUICulture. That still does not guarantee it will be set correctly, unmanaged code you call can change it and the CLR cannot do anything about it. In other words, a bug will be much harder to diagnose. But at least you have some idea when it might change.

更新:此问题已在 .NET 4.6 中彻底修复,文化现在从一个线程流向另一个线程,CultureInfo.DefaultThreadCurrentCulture hack 不再需要也不再有用.在 MSDN 文章中记录了 CultureInfo.CurrentCulture.现在所写的细节似乎并不完全正确,当我测试它时它总是流动的,而 DefaultThreadCurrentCulture 似乎不再起作用.

UPDATE: this problem was fixed thoroughly in .NET 4.6, culture now flows from one thread to another and the CultureInfo.DefaultThreadCurrentCulture hack is not longer necessary nor useful. Documented in the MSDN article for CultureInfo.CurrentCulture. Details as written right now do not appear to be entirely correct, it always flowed when I tested it and DefaultThreadCurrentCulture appear to play no role at all anymore.

这篇关于保持 CurrentCulture 处于异步/等待状态的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆