Warum ist CurrentCulture eine Eigenschaft von Thread?

7

Es fällt mir auf, dass die aktuelle Kulturinformation (CurrentCulture und / oder CurrentUICulture) eine Eigenschaft des laufenden Threads ist. Zumindest scheint es so zu sein, dass der Umfang einer solchen Sache auf der Prozessebene eine Ebene höher sein sollte.

Aber diese Dinge machen normalerweise Sinn, sobald Sie die Begründung hören. Es könnte aufschlussreich sein, herauszufinden, warum die .NET-Designer entschieden haben, dass Thread der richtige Ort für diese Eigenschaft ist.

    
I. J. Kennedy 14.11.2010, 03:32
quelle

4 Antworten

10

Für den Anfang war es nicht wirklich ihre Wahl. Diese Entscheidung wurde lange vor dem Start getroffen, Kultur ist eine Eigenschaft eines Betriebssystem-Threads. Sehen Sie sich zum Beispiel die SDK-Dokumente für die API-Funktionen Get / SetThreadLocale () an.

Das erklärt es nicht vollständig, sie haben andere OS-Funktionen virtualisiert, obwohl diese sehr schwer zu virtualisieren sind, weil so viele APIs kultursensibel sind, besonders COM-sensitive.

Der nächste gute Grund liegt darin, dass es so extrem schwierig ist, die Kultur im gesamten Prozess zu ändern. Es ist eine unlösbare Wettlaufbedingung. Ein anderer Thread ist möglicherweise gerade dabei, Daten mit Kulturaffinität zu formatieren. Während eine Sperre verhindern würde, dass sie Kultureigenschaften gerade während der Änderung verwendet, kann sie nicht verhindern, dass sie sich mitten in einer Kette von Formatierungsaufrufen ändert. Es würde erfordern, dass sie eine Art globale Sperre übernehmen und sie für die Dauer des Formatierungsjobs halten. Deadlock ist sehr wahrscheinlich.

Es gibt noch einen anderen Aspekt, den ich für das eigentliche Problem halte. Es hängt mit der Thread.ExecutionContext-Eigenschaft zusammen. Das Framework verwendet dies, um den Thread-Status von einem Thread zu einem anderen zu "fließen". Sehr unklar, aber wichtig, um Dinge wie den Sicherheitskontext auf einen Worker-Thread zu übertragen. Es wäre ideal gewesen, wenn dieser Kontext auch die Kultur durchdringen könnte, so dass Sie sicher sein können, dass jeder der von Ihnen angefangenen Mitarbeiter dieselbe Kultur hat, die Sie ausgewählt haben, und nicht die Standardeinstellung des Betriebssystems.

Es ist nicht, ich weiß nicht wirklich warum. Wahrscheinlich weil ich den allerersten Grund angegeben habe. Das macht es jedoch sehr gefährlich, die Kultur eines Threads zu ändern. Die Art von Bugs, die dazu führen können, sind sehr subtil. Wie das Erstellen eines SortedDictionary mit einer Zeichenfolge als Schlüssel in Ihrem Hauptthread mit einer Standardkultur, die nicht zum Betriebssystem gehört. Dann wird festgestellt, dass ein Worker-Thread gelegentlich keine Daten mehr finden kann, da die Sortierregeln für die Zeichenfolge unterschiedlich sind.

BEARBEITEN: Dieses Problem wird in .NET 4.5 behoben. Es unterstützt die neuen statischen Eigenschaften CultureInfo.DefaultThreadCurrentCulture und DefaultThreadCurrentUICulture.

EDIT2: culture läuft nun wie im 4. Abschnitt in .NET 4.6 beschrieben. Dies sollte alle Bedenken lindern.

    
Hans Passant 14.11.2010, 11:46
quelle
6

Ich werde eine Aufnahme machen - vielleicht, weil Sie mehrere gleichzeitige Threads mit unterschiedlichen Kulturen benötigen würden? Wenn Sie an eine mehrsprachige ASP.net-Website denken, möchten Sie nicht, dass der Prozess an eine Sprache gebunden ist ... eine Webanfrage könnte EN-US und eine andere FR-FR sein.

    
kimphamg 14.11.2010 03:37
quelle
2

Fenstergriffe sind selbst Thread-spezifisch. Sie sollten nie ein Fenster-Handle (für ein Top-Level-Fenster, Untersteuerelement usw.) im Kontext eines anderen Threads verwenden, da der Code, der die Fensterbehandlung (GDI) implementiert, selbst nicht Thread-sicher ist. Da die UICulture fensterspezifisch ist, bedeutet dies, dass sie auch auf der Thread-Ebene definiert wird.

Andere GUI-Aspekte sind auch Thread-spezifisch, wie das aktive Fenster und der Fokus. Obwohl es eine API gibt, kann ich mich nicht an den Namen erinnern, der den UI-Kontext aus verschiedenen Threads zusammenfügt, so dass das aktive Fokusfenster zwischen mehreren Benutzeroberflächen-Threads geteilt wird.

    
Phil Wright 14.11.2010 03:36
quelle
2

Die CurrentCulture ist nichts anderes als ein Verweis auf eine CultureInfo, so dass nicht viel verloren gehen würde, wenn man sie am Thread hängen lässt (nur die Erinnerung für eine Referenz). Gleichzeitig erhalten Sie die Möglichkeit, Benutzern zu erlauben, die aktuelle Kultur pro Thread fein zu steuern - was sich in einigen Arten von Anwendungen als wichtig erweist.

Ein Grund, warum es so feinkörnig ist, könnte für nicht englischsprachige Benutzer moderner Software offensichtlich sein. Ich für meinen Teil muss regelmäßig die Tastatur in Windows wechseln und kann dies leicht mit einem globalen Tastaturkürzel tun. Mit der CultureInfo im Thread können wir eine ähnliche Logik in unseren .NET-Apps problemlos implementieren, ohne diese Informationen pro Prozess ändern zu müssen.

Anwendungsbeispiele, die Ihnen einfallen:

  1. Ich möchte vielleicht eine Verknüpfung, die die Kultur in meinem Programm für eine kurze Zeit auf Anfrage für den aktuellen Benutzer ändern würde (viele Anwendungen müssen mehrere Benutzer auf derselben Arbeitsstation und in derselben Sitzung zulassen). Aber derselbe Prozess muss möglicherweise weiterhin die standardmäßige CultureInfo auf dem Computer verwenden, um z. Loggen Sie immer mit dem gleichen Timestamp-Format ein.

  2. Möglicherweise verfügen Sie auch über eine Berichtslösung, mit der Berichte für mehrere Zweige eines globalen Unternehmens in ihrer jeweiligen Kultur ausgegeben werden. Ihr Entwurf wäre weniger eingeschränkt, wenn Sie die CultureInfo pro Thread ändern könnten.

  3. Ein weiterer Grund wäre, wenn Sie mit einer bestimmten Kultur in eine Datei schreiben möchten, aber die Kultur in Ihren Schreibfunktionen nicht angeben möchten (z. B. weil diese Funktionen bereits geschrieben wurden). Dann können Sie diese Logik leicht ändern, ohne sie in anderen Threads zu ändern, die möglicherweise die Standardkultur verwenden.

steinar 14.11.2010 04:22
quelle