2010-03-05 13 views
19

Mi piacerebbe impostare la cultura per tutta la mia applicazione. Ho provato quanto segue:C# Background Culture del lavoratore

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

Si lavora per il thread corrente, ma in seguito ho creare e avviare un thread in background operaio. Quando creo il worker, il thread corrente viene eseguito con wantedCulture ma il thread worker verrà eseguito con la cultura del mio computer.

Qualche idea per impostare la cultura per l'intera applicazione?

risposta

34

NOTA: materiale datato, assicuratevi di leggere l'aggiornamento al fondo per le modifiche in .NET 4.6

Sì, questo è un comune richiesta ma non è disponibile. Windows inizializza sempre un thread del sistema operativo sull'LCID predefinito del sistema, configurato nell'applet Opzioni internazionali e della lingua nel Pannello di controllo. È possibile ignorare questo finché si creano i thread da soli. Ma ciò non è pratico per thread e thread threadpool che potrebbero essere stati creati da un qualche tipo di codice non gestito che esegue il processo, come un server COM.

Quest'ultimo caso è il problema. .NET non ha problemi a eseguire codice gestito su thread creati da codice non gestito. Ma non può fare nulla sul modo in cui il thread è inizializzato. Questo è vero per CurrentUICulture ma anche per cose più oscure come Thread.SetApartmentState(). Non sottovalutare la probabilità che un thread di questo tipo esegua codice nel tuo programma, i server COM scritti da Microsoft sono molto felici.

Dovrai versare il codice con un pettine a denti fini e trovare qualsiasi codice che possa essere eseguito su un filo che non hai creato. Qualsiasi gestore di eventi è sospetto, come qualsiasi metodo BeginXxx() che ha un callback. BackgroundWorker è sicuramente il problema minore.

Non sovrascrivere la cultura del thread può produrre molto bug difficile e difficile da diagnosticare. Un buon esempio sarebbe un SortedList che digita su una stringa. Quando viene eseguito con la cultura sbagliata, casualmente non riuscirà a trovare gli elementi effettivamente presenti nella lista. Causato dall'elenco non più ordinato in un'altra cultura con regole di confronto diverse.

Se sono riuscito a spaventarti abbastanza, ho ricevuto il mio messaggio. Questo è successo a me, facendo il debug di un problema con un programma molto grande che si è comportato male su una macchina danese. Non avevamo una localizzazione danese e abbiamo costretto l'interfaccia utente a girare in inglese. Un thread di lavoro utilizzava un albero rosso-nero che aveva una stringa come chiave. Falliva casualmente quando gli veniva chiesto di trattare con Åårdvårks. Mi ci sono voluti una settimana.


Aggiornamento: questo problema è stato risolto in .NET 4.5. La classe CultureInfo ora ha un DefaultThreadCurrentCulture e DefaultThreadCurrentUICulture. Se impostato, verrà utilizzato per inizializzare la cultura di qualsiasi thread gestito anziché la cultura di sistema predefinita di Windows.Il modo in cui interagisce con i thread avviati dal codice nativo e che inserisci codice gestito non mi è ancora chiaro.


Aggiornamento: questo problema ha avuto una soluzione più approfondita in .NET 4.6. La cultura ora scorre automaticamente, il comportamento ideale. L'articolo MSDN per CultureInfo.CurrentCulture() ne parla. Le informazioni fornite sono ancora confuse, sperimentalmente sembra anche che fluisca su un oggetto Thread e non solo su un thread Task o Threadpool e DefaultThreadCurrentCulture non viene utilizzato. Due passi avanti, un passo indietro, si consiglia di testare.

1

La mia soluzione doveva avere una proprietà di cultura centrale (Application.CurrentCulture è per-thread) e impostare la cultura di thread corrente su questo all'inizio di un thread di lavoro. Un sistema di lavoro aiuta in questo modo, dal momento che è possibile eseguire facilmente codice generico prima e dopo l'elemento di lavoro e la classe del sistema di lavoro può contenere la cultura accessibile dai suoi lavori, quindi non è necessario disporre di globals.

0

Non è possibile eseguire questa operazione per ogni thread appena creato. Dovresti farlo a mano (ma non credo che impostare la cultura per i thread del pool di thread sia una buona idea!). Forse l'applicazione deve dipende Application.CurrentCulture o qualche altra roba globale ..

1

In poche parole; Non farlo.

Non eseguire alcuna formattazione specifica della lingua su nessun altro thread rispetto alla filettatura principale (Thread.CurrentThread). Ottenere la cultura corretta su altri thread - ogni altro thread creato - è solo un dolore e prima o poi ti dimenticherai di impostarlo correttamente. Meglio evitare semplicemente il dolore tutti insieme e solo fare la formattazione specifica per la cultura, la conversione, ecc. Sul thread che si garantisce che sia nelle impostazioni di cultura corrette.

0

di Windows inizializza sempre un thread del sistema operativo per il LCID default del sistema, configurato nel applet Opzioni internazionali e della lingua nel controllo Panel.

Purtroppo devo essere in disaccordo con questo e ho trovato il contrario.

Il sistema è stato installato come inglese americano. È andato al pannello di controllo ha cambiato tutto in danese e copiato su tutti gli account. Riavviato.

L'app per la console di esecuzione viene eseguita in danese. Esegui l'app web chiedi al browser che dice danese. Avvia la discussione dall'app Web ed è avviata poiché gli Stati Uniti non sono danesi e non riesco a capire perché.

0

So che l'argomento è vecchio ma mi sono trovato in un problema di "thread con OS culture".

L'ho risolto così: poiché BackgroundWorker è in un UserControl (sarebbe valido se si trova in un modulo e così via ...) imposto un campo in UserControl (o Form) quando viene creato. Nel gestore di eventi DoWork utilizzo questo campo nelle mie operazioni. Qui il codice:

/// <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); 
    } 
Problemi correlati