Подтвердить что ты не робот

Культура С# BackgroundWorker

Мне хотелось бы настроить культуру для всего моего приложения. Я попробовал следующее:

Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(wantedCulture);
Thread.CurrentThread.CurrentUICulture = CultureInfo.CreateSpecificCulture(wantedCulture);
Application.CurrentCulture = CultureInfo.CreateSpecificCulture(wantedCulture);

Он работает для текущего потока, но позже я создаю и запускаю поток рабочего фона. Когда я создаю рабочего, текущий поток выполняется с помощью wantCulture, но рабочий поток будет работать с моей компьютерной культурой.

Любые идеи по настройке культуры для всего приложения?

4b9b3361

Ответ 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);
    }