2010-11-14 4 views
7

Мне кажется странным выбором дизайна, что текущая информация о культуре (CurrentCulture и/или CurrentUICulture) является свойством работающего потока. По крайней мере, похоже, что объем такой вещи должен быть на одном уровне вверх, на уровне процесса.Почему CurrentCulture - свойство Thread?

Но эти вещи обычно имеют смысл, когда вы слышите обоснование. Возможно, было бы интересно узнать, почему разработчики .NET решили, что Thread был подходящим местом для размещения этого свойства.

ответ

10

Для начала это был не их выбор. Это решение было принято задолго до того, как они начали работу, а культура - свойство потока операционной системы. Просмотрите документы SDK для функций API Get/SetThreadLocale(), например.

Это не полностью объясняет это, они виртуализировали другие функции ОС, хотя этот очень трудно виртуализировать, потому что так много API-интерфейсов чувствительны к культуре, особенно COM-версии.

Следующая веская причина заключается в том, что изменить культуру в масштабе всего процесса так сложно реализовать. Это состояние неразрешимой гонки. Некоторая другая нить может быть в центре форматирования данных, имеющих культурную близость. Хотя блокировка будет работать, чтобы предотвратить использование свойств культуры так же, как она меняется, она может не предотвратить ее изменение в середине цепочки форматирования вызовов. Это потребовало бы, чтобы они взяли какой-то глобальный замок и удерживали его на время работы по форматированию. Тупик очень наверняка.

Есть еще один аспект этого, тот, который я считаю реальной проблемой. Это связано с свойством Thread.ExecutionContext. Структура использует это для «потока» состояния потока из одного потока в другой. Очень неясный, но важный, чтобы наполнить такие вещи, как контекст безопасности, на рабочий поток. Было бы идеально, если бы этот контекст мог также наполнить культуру, чтобы вы могли быть уверены, что любой из рабочих, которых вы начинаете, имеет ту же культуру, которую вы выбрали, а не по умолчанию для операционной системы.

Это не так, я действительно не знаю, почему. Наверное, потому что первая причина, которую я дал. То, что делает, тем не менее, очень опасно менять культуру нити. Ошибки, которые могут вызывать, - очень тонкие. Подобно созданию SortedDictionary со строкой в ​​качестве ключевого элемента основного потока с нестандартной культурой по умолчанию. Затем выяснение, что рабочий поток не может время от времени находить материал назад, потому что правила сортировки строк различны.


EDIT: есть некоторое облегчение от этой проблемы в .NET 4.5, он поддерживает новый статический CultureInfo.DefaultThreadCurrentCulture и свойства DefaultThreadCurrentUICulture.


EDIT2: культура теперь протекает, как описано в четвертом абзаце в .NET 4.6. Это должно облегчить все проблемы.

2

Оконные ручки сами по себе относятся к конкретным темам. Вы никогда не должны использовать дескриптор окна (для окна верхнего уровня, дочерний элемент управления и т. Д.) В контексте другого потока, потому что код, который реализует обработку окон (GDI), сам по себе не является потокобезопасным. Поскольку UICulture является конкретным окном, это означает, что он также определяется на уровне нити.

Другие аспекты GUI также относятся к потоку, например, к активному окну и фокусу. Хотя есть API, я не могу вспомнить имя, которое объединяет контекст пользовательского интерфейса из разных потоков вместе, так что фокус, активное окно разделяется между несколькими потоками пользовательского интерфейса.

6

Я сделаю снимок - может быть, потому, что вам понадобится несколько одновременных потоков с использованием другой культуры? Если вы думаете о многоязычном веб-сайте asp.net, вы не хотите, чтобы процесс был привязан к одному языку ... веб-запрос мог быть EN-US и еще одним fr-FR.

2

The CurrentCulture - это не что иное, как ссылка на CultureInfo, поэтому не так много теряется, позволяя ему висеть на потоке (просто память для одной ссылки). В то же время вы получаете возможность разрешить пользователям точно контролировать текущую культуру в потоке, что оказывается важным в некоторых видах приложений.

Одна из причин того, что это мелкозернистая может быть более очевидной для пользователей, не говорящих по-английски, о современном программном обеспечении. Мне нужно регулярно переключаться с клавиатуры в Windows, и я могу сделать это с помощью одного глобального сочетания клавиш. Наличие CultureInfo в потоке позволяет нам легко реализовать аналогичную логику в наших приложениях .NET без необходимости изменять эту информацию для каждого процесса.

примеры использования, которые приходят на ум:

  1. я мог бы ярлык, который изменит культуру в моей программе в течение короткого периода времени, по запросу текущего пользователя (многие приложения необходимо разрешить несколько пользователей на той же рабочей станции и в том же сеансе). Но этот же процесс, возможно, придется продолжать использовать значение CultureInfo по умолчанию на машине, например. log всегда с одним и тем же временным типом.

  2. Возможно, у вас также есть решение для отчета, которое вывело бы отчеты для нескольких филиалов глобальной компании, каждый в своей собственной культуре. Ваш дизайн будет менее ограниченным, если вы можете изменить CultureInfo на поток.

  3. Другой причиной может быть запись в файл с использованием определенной культуры, но вы не хотите указывать культуру в своих функциях записи (например, поскольку эти функции уже написаны). Затем вы можете легко изменить эту логику, не изменяя ее на других потоках, которые могут выполнять работу, требующую культуры по умолчанию.

Смежные вопросы