Я хотел бы установить культуру для своего целого приложения. Я попробовал следующее:
Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(wantedCulture);
Thread.CurrentThread.CurrentUICulture = CultureInfo.CreateSpecificCulture(wantedCulture);
Application.CurrentCulture = CultureInfo.CreateSpecificCulture(wantedCulture);
Это работает на текущий поток, но позже я создаю и запускаю фоновый рабочий поток. Когда я создаю рабочего, текущий поток выполняется с wantedCulture, но рабочий поток будет работать с культурой моего компьютера.
Какие-либо идеи установить культуру для целого приложения?
ПРИМЕЧАНИЕ: датированный материал, обязательно прочтите «Обновление» внизу, чтобы узнать об изменениях в .NET 4.6
Да, это обычный запрос, но он недоступен. Windows всегда инициализирует поток ОС с использованием системного идентификатора LCID по умолчанию, настроенного в апплете «Язык и региональные стандарты» на панели управления. Вы можете переопределить это, если сами создаете потоки. Но это непрактично для потоков пула потоков и потоков, которые могли быть созданы каким-то неуправляемым кодом, выполняющим ваш процесс, например COM-сервером.
Последний случай представляет собой проблему. .NET не имеет проблем с запуском управляемого кода в потоках, созданных неуправляемым кодом. Но он ничего не может сделать с инициализацией потока. Это верно для CurrentUICulture, но также и для более непонятных вещей, таких как Thread.SetApartmentState (). Не стоит недооценивать вероятность того, что такой поток запускает код в вашей программе, COM-серверы, написанные Microsoft, очень ориентированы на потоки.
Вам нужно будет проработать свой код зубчатой гребенкой и найти любой код, который может выполняться в потоке, который вы не создавали. Любой обработчик событий является подозрительным, как и любой метод BeginXxx (), у которого есть обратный вызов. BackgroundWorker - определенно меньшая проблема.
Отсутствие переопределения культуры потока может привести к очень очень тонким и трудно диагностируемым ошибкам. Хорошим примером может служить SortedList, который содержит ключи в строке. При запуске с неправильной культурой случайным образом не удается найти элементы, которые действительно присутствуют в списке. Причина в том, что список больше не сортируется в другой культуре с другими правилами сопоставления.
Если мне удавалось достаточно вас напугать, то я передал свое сообщение. Это случилось со мной при отладке проблемы с очень большой программой, которая неправильно работала на датской машине. У нас не было датской локализации, и пользовательский интерфейс был вынужден работать на английском языке. Рабочий поток использовал красно-черное дерево, в котором в качестве ключа была строка. Когда его попросили разобраться с Åardvårks, он случайно потерпел неудачу. У меня ушла неделя.
Обновление: эта проблема устранена в .NET 4.5. Класс CultureInfo теперь имеет DefaultThreadCurrentCulture и DefaultThreadCurrentUICulture. Если он установлен, он будет использоваться для инициализации культуры любого управляемого потока вместо культуры системы Windows по умолчанию. Мне еще не ясно, как именно он взаимодействует с потоками, которые были запущены собственным кодом и вводят управляемый код.
Обновление: эта проблема была решена более тщательно в .NET 4.6. Культура сейчас течет автоматически, идеальное поведение. Об этом говорится в статье MSDN для CultureInfo.CurrentCulture () . Предоставленная информация пока что сбивает с толку, экспериментально она также передается объекту Thread, а не только потоку Task или threadpool, а DefaultThreadCurrentCulture не используется. Два шага вперед, один шаг назад, рекомендуется тестирование.
Моим решением было иметь центральное свойство культуры (Application.CurrentCulture - per-thread) и устанавливать текущую культуру потока в это свойство в начале рабочего потока. Система заданий помогает в этом, поскольку вы можете легко выполнять общий код до и после рабочего элемента, а класс системы заданий может хранить культуру, доступную для его заданий, так что вам не нужны глобальные файлы.
Вы не можете сделать это для каждого вновь созданного потока. Вы должны делать это вручную (но я не думаю, что установка культуры для потоков пула потоков - хорошая идея!). Возможно, ваше приложение должно зависеть от Application.CurrentCulture или каких-то других глобальных вещей ..