2010-03-05 8 views
19

Ich möchte die Kultur für meine ganze Anwendung setzen. Ich habe versucht, die folgenden:C# BackgroundWorker's culture

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

Es funktioniert für den aktuellen Thread, aber ich später erstellen und einen Hintergrund-Worker-Thread starten. Wenn ich den Worker erstelle, wird der aktuelle Thread mit der "willedCulture" ausgeführt, aber der Worker-Thread wird mit der Kultur meines Computers ausgeführt.

Irgendwelche Ideen, um die Kultur für die gesamte Anwendung zu setzen?

Antwort

34

HINWEIS: datiertes Material, müssen Sie die Aktualisierung an der Unterseite für Änderungen in .NET 4.6

Ja zu lesen, ist dies ein weit verbreitete Anfrage, aber es ist nicht verfügbar. Windows initialisiert einen Betriebssystemthread immer mit der Standard-LCID des Systems, die im Applet "Regions- und Sprachoptionen" in der Systemsteuerung konfiguriert wurde. Sie können dies außer Kraft setzen, solange Sie die Threads selbst erstellen. Aber das ist nicht praktisch für Threadpool-Threads und Threads, die möglicherweise von einer Art nicht verwaltetem Code erstellt wurden, der Ihren Prozess ausführt, wie ein COM-Server.

Der letztere Fall ist das Problem. .NET hat keine Probleme, verwalteten Code in Threads auszuführen, die mit nicht verwaltetem Code erstellt wurden. Aber es kann nichts über die Art und Weise tun, wie der Thread initialisiert wird. Das gilt für CurrentUICulture, aber auch für etwas obskureres wie Thread.SetApartmentState(). Unterschätzen Sie nicht die Wahrscheinlichkeit, dass ein solcher Thread Code in Ihrem Programm ausführt, COM-Server, die von Microsoft geschrieben wurden, sind sehr Thread-glücklich.

Sie müssen durch Ihren Code mit einem feinzackigen Kamm gießen und finden Sie Code, der auf einem Thread ausgeführt werden könnte, den Sie nicht erstellt haben. Jeder Event-Handler ist verdächtig, ebenso wie jede BeginXxx() -Methode, die einen Callback hat. BackgroundWorker ist definitiv das kleinere Problem.

Nicht überschreiben die Kultur des Threads kann produzieren sehr subtile und schwer zu diagnostizieren Bugz. Ein gutes Beispiel wäre eine SortedList, die auf eine Zeichenfolge eingibt. Wenn es mit der falschen Kultur ausgeführt wird, findet es zufällig keine Elemente, die tatsächlich in der Liste vorhanden sind. Dadurch, dass die Liste nicht mehr in einer anderen Kultur mit anderen Sortierregeln sortiert ist.

Wenn ich Sie genug erschrecken konnte, dann habe ich meine Nachricht über. Dies ist mir passiert, als ich ein Problem mit einem sehr großen Programm, das sich auf einer dänischen Maschine verharmlost hat, debuggte. Wir hatten keine dänische Lokalisierung und zwangen die Benutzeroberfläche, in Englisch zu laufen. Ein Worker-Thread verwendete einen rot-schwarzen Baum, der eine Zeichenfolge als Schlüssel hatte. Es scheiterte nach dem Zufallsprinzip, als sie gebeten wurde, sich mit Åårdvårks zu befassen. Nahm mich eine Woche.


Update: Dieses Problem wurde in .NET 4.5 behoben. Die CultureInfo-Klasse verfügt jetzt über DefaultThreadCurrentCulture und DefaultThreadCurrentUICulture. Wenn diese Option festgelegt ist, wird sie verwendet, um die Kultur eines verwalteten Threads anstelle der Standard-Windows-Systemkultur zu initialisieren.Wie es mit Threads interagiert, die durch nativen Code gestartet wurden und verwalteten Code eingeben, ist mir noch nicht klar.


Update: Dieses Problem hatte eine gründlichere Lösung in .NET 4.6. Kultur fließt jetzt automatisch, das ideale Verhalten. Der MSDN-Artikel für CultureInfo.CurrentCulture() spricht darüber. Die bereitgestellten Informationen sind noch verwirrend, experimentell scheint sie auch zu einem Thread-Objekt zu fließen und nicht nur zu einem Task- oder Threadpool-Thread und DefaultThreadCurrentCulture wird nicht verwendet. Zwei Schritte vorwärts, ein Schritt zurück, Testen wird empfohlen.

1

Meine Lösung war eine zentrale culture -Eigenschaft (Application.CurrentCulture ist pro-Thread) und legen Sie die aktuelle Thread-Kultur zu diesem am Anfang eines Worker-Thread. Ein Jobsystem hilft dabei, da Sie dann einfach generischen Code vor und nach dem Workitem ausführen können, und die Jobsystemklasse kann die Kultur für ihre Jobs verfügbar halten, so dass Sie keine Globals benötigen.

0

Sie können dies nicht für jeden neu erstellten Thread tun. Sie sollten es von Hand tun (aber ich denke nicht, dass das Setzen von Kultur für Thread-Pool-Threads eine gute Idee ist!). Vielleicht sollen Sie Ihre Anwendung auf Application.CurrentCulture oder einer anderen globalen Sachen abhängt ..

1

Einfach ausgedrückt; Tu es nicht.

Führen Sie keine kulturspezifische Formatierung für einen anderen Thread als den Hauptthread aus (Thread.CurrentThread). Die richtige Kultur auf anderen Threads zu bekommen - jeder andere Thread erstellt - ist nur ein Schmerz und früher oder später wirst du vergessen, es richtig zu setzen. Lieber vermeiden Sie den ganzen Schmerz und machen nur kulturspezifische Formatierungen, Konvertierungen usw. für den Thread, bei dem Sie garantiert die richtigen Kultureinstellungen haben.

0

von Windows initialisiert immer ein OS-Thread auf den Systemstandard LCID, konfiguriert in der Regions- und Sprachoptionen Applet in der Systemsteuerung -Panel.

Leider muss ich dem widersprechen und habe das Gegenteil gefunden.

System wurde als US-Englisch installiert. Ging an Systemsteuerung änderte alles auf Dänisch und kopierte auf alle Konten. Neu gestartet.

Run Konsole App es läuft in Dänisch. Führen Sie Web-App-Browser fragt es dänisch. Launch Thread von Web-App und es ist als US nicht dänisch gestartet und ich kann nicht herausfinden, warum.

0

Ich weiß, das Thema ist alt, aber ich fand mich in einem "Thread mit OS-Kultur" Problem.

Ich löste es so: wie der BackgroundWorker in einem UserControl ist (es wäre gültig, wenn es in einem Formular ist usw.) Ich setze ein Feld im UserControl (oder Form), wenn es konstruiert ist. Im DoWork-Event-Handler verwende ich dieses Feld in meinen Operationen. Hier der Code:

/// <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); 
    } 
Verwandte Themen