Культура С# BackgroundWorker
Мне хотелось бы настроить культуру для всего моего приложения. Я попробовал следующее:
Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(wantedCulture);
Thread.CurrentThread.CurrentUICulture = CultureInfo.CreateSpecificCulture(wantedCulture);
Application.CurrentCulture = CultureInfo.CreateSpecificCulture(wantedCulture);
Он работает для текущего потока, но позже я создаю и запускаю поток рабочего фона. Когда я создаю рабочего, текущий поток выполняется с помощью wantCulture, но рабочий поток будет работать с моей компьютерной культурой.
Любые идеи по настройке культуры для всего приложения?
Ответы
Ответ 1
ПРИМЕЧАНИЕ: датированный материал, обязательно прочтите "Обновление внизу" для изменений в .NET 4.6
Да, это общий запрос, но он недоступен. Windows всегда инициализирует поток ОС для стандартного LCID системы, настроенного в апплете региональных и языковых параметров в панели управления. Вы можете переопределить это, если сами создаете потоки. Но это нецелесообразно для потоков threadflow и потоков, которые могли быть созданы каким-то неуправляемым кодом, выполняющим ваш процесс, например, COM-сервером.
Последний случай - проблема. У .NET нет проблем с запуском управляемого кода в потоках, созданных неуправляемым кодом. Но он не может ничего сделать, как инициализировать поток. Это верно для CurrentUICulture, но также и для более неясных вещей, таких как Thread.SetApartmentState(). Не стоит недооценивать вероятность того, что такой поток запускает код в вашей программе, серверы COM, написанные Microsoft, очень довольны.
Вам нужно будет вылить свой код с помощью тонкой зубчатой гребенки и найти любой код, который может выполняться в потоке, который вы не создали. Любой обработчик событий является подозрительным, как и любой метод BeginXxx(), который имеет обратный вызов. BackgroundWorker определенно является меньшей проблемой.
Не переопределяя культуру нитей, можно произвести очень тонкую и трудную диагностику bugz. Хорошим примером будет SortedList, который содержит ключи в строке. При запуске с неправильной культурой он случайным образом не сможет найти элементы, которые действительно присутствуют в списке. Вызывается тем, что список больше не сортируется в другой культуре с различными правилами сортировки.
Если бы мне удалось напугать вас достаточно, я получил свое сообщение. Это случилось со мной, отлаживая проблему с очень большой программой, которая плохо себя ведет на датской машине. У нас не было датской локализации, и пользовательский интерфейс был запущен на английском языке. Рабочий поток использовал красно-черное дерево с строкой в качестве ключа. Это было случайно, когда его попросили разобраться с åårdvårks. Взял меня на неделю.
Обновление: эта проблема была рассмотрена в .NET 4.5. Класс CultureInfo теперь имеет DefaultThreadCurrentCulture и DefaultThreadCurrentUICulture. Когда он установлен, он будет использоваться для инициализации культуры любого управляемого потока вместо стандартной системы Windows. То, как он взаимодействует с потоками, начатыми с помощью собственного кода, и вводить управляемый код, пока не ясен.
Обновление: эта проблема имела более полное решение в .NET 4.6. Культура теперь течет автоматически, идеальное поведение. Об этом говорит статья MSDN для CultureInfo.CurrentCulture(). Предоставленная информация еще не сбивает с толку, экспериментально она также перетекает в объект Thread, а не только поток Task или threadpool, а DefaultThreadCurrentCulture не используется. Два шага вперед, один шаг назад, тестирование рекомендуется.
Ответ 2
Мое решение состояло в том, чтобы иметь свойство центральной культуры (Application.CurrentCulture - для потока) и установить текущую культуру потока в это в начале рабочего потока. С этим справляется система заданий, так как вы можете легко выполнять общий код до и после рабочего элемента, а класс системы заданий может поддерживать доступность культуры по своим заданиям, поэтому вам не нужны глобальные переменные.
Ответ 3
Проще говоря; Не делайте этого.
Не делайте никакого специального форматирования в любом другом потоке, кроме основного потока (Thread.CurrentThread
). Получение правильной культуры на других потоках - любая другая созданная нить - это просто боль, и рано или поздно вы забудете правильно ее установить. Лучше просто избегать боли все вместе и делать только форматирование, преобразование и т.д. В потоке, который гарантированно будет в правильных настройках культуры.
Ответ 4
Вы не можете сделать это для каждого вновь созданного потока. Вы должны сделать это вручную (но я не думаю, что настройка культуры потоков потоков потоков - это хорошая идея!). Возможно, ваше приложение должно зависеть от Application.CurrentCulture или какого-либо другого глобального материала.
Ответ 5
Windows всегда инициализирует поток ОС для LCID системы по умолчанию, настроен в апплете региональных и языковых параметров в элементе управления Панель.
К сожалению, я не согласен с этим и нашел обратное.
Система была установлена как английский.
Пошел на панель управления, изменил все на датский язык и скопировал все учетные записи.
Rebooted.
Запустить консольное приложение на датском языке.
Запустить веб-приложение спросить браузер он говорит, датский.
Запустите поток из веб-приложения, и он запущен как США, а не датский, и я не могу понять, почему.
Ответ 6
Я знаю, что тема старая, но я оказался в проблеме "поток с ОС".
Я решил это так: поскольку BackgroundWorker находится в UserControl (он был бы действителен, если он находится в форме и т.д.). Я устанавливаю поле в UserControl (или Form), когда оно построено. В обработчике событий DoWork я использую это поле в своих операциях. Здесь код:
/// <summary>
/// Culture in which the GUI creates the control.
/// </summary>
private readonly CultureInfo _currentCulture;
/// <summary>
/// Default constructor.
/// </summary>
public MyControl()
{
InitializeComponent();
_currentCulture = CultureInfo.CurrentUICulture;
}
private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
ExampleClass.DoCultureDependentOperation(_currentCulture);
}