2010-03-05 37 views
19

我非常想爲我的整個應用程序設置文化。我嘗試了以下方法:C#BackgroundWorker的文化

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

它適用於當前線程,但稍後創建並啓動後臺工作線程。當我創建worker時,當前線程使用wantedCulture執行,但工作線程將與我的計算機文化一起運行。

任何想法爲整個應用程序設置文化?

回答

34

注:凡是注日期的材料,一定要在底部閱讀更新變化的.NET 4.6

是的,這是一種常見的請求但它不可用。 Windows總是將操作系統線程初始化爲系統默認的LCID,在控制面板中的區域和語言選項小程序中進行配置。只要您自己創建線程,就可以覆蓋它。但是對於線程池線程和線程來說,這可能是由運行你的進程的某種非託管代碼(例如COM服務器)創建的。

後一種情況是問題所在。運行由非託管代碼創建的線程上的託管代碼時,.NET沒有問題。但是它不能對線程初始化的方式做任何事情。對於CurrentUICulture來說也是如此,但對於Thread.SetApartmentState()等更隱晦的東西也是如此。不要低估這種線程在您的程序中運行代碼的可能性,由微軟編寫的COM服務器非常高興。

你將不得不通過你的代碼精細齒梳,並找到任何代碼可能在你沒有創建的線程上運行。任何事件處理程序都是可疑的,就像任何具有回調的BeginXxx()方法一樣。 BackgroundWorker絕對是一個較小的問題。

不壓倒線程的文化可以產生微妙和難以診斷bugz。一個很好的例子是一個SortedList,它是一個字符串的鍵。當運行錯誤的文化時,它隨機將無法找到實際存在於列表中的元素。由於排序規則不同,導致列表不再被排序在另一種文化中。

如果我設法嚇唬你,那麼我得到了我的信息。這發生在我身上,用一個在丹麥機器上運行不正常的非常大的程序來調試問題。我們沒有丹麥本地化,並強制用戶界面以英文運行。工作者線程使用了一個以字符串作爲關鍵字的紅黑樹。當被要求與Åårdvårks打交道時,它隨機失敗。花了我一個星期。


更新:此問題已在.NET 4.5中解決。 CultureInfo類現在有一個DefaultThreadCurrentCulture和DefaultThreadCurrentUICulture。設置時,它將用於初始化任何託管線程的文化,而不是默認的Windows系統文化。它究竟是如何與本地代碼開始的線程進行交互並輸入托管代碼的,我還不清楚。


更新:此問題在.NET 4.6中有更徹底的解決方案。文化現在自動流動,理想的行爲。 MSDN文章CultureInfo.CurrentCulture()談論它。提供的信息仍然令人困惑,實驗上,它似乎也流向了一個Thread對象,而不僅僅是一個Task或線程池線程,並且不使用DefaultThreadCurrentCulture。前進兩步,退一步,建議測試。

1

我的解決方案是有一箇中心文化屬性(Application.CurrentCulture是每線程),並在工作線程開始時將當前線程文化設置爲此。一個工作系統可以解決這個問題,因爲你可以在工作項目之前和之後輕鬆地執行通用代碼,而工作系統類可以保持作業可訪問的文化,所以你不需要全局變量。

0

對於每個新創建的線程都無法做到這一點。你應該手工做(但我不認爲線程池線程的文化是一個好主意!)。也許您的應用程序應該依賴於Application.CurrentCulture或其他一些全球性的東西..

1

簡而言之; 不要做

不要在主線程(Thread.CurrentThread)之外的任何其他線程上執行任何文化特定的格式。在其他線程(創建其他線程)上獲得正確的文化只是一種痛苦,遲早你會忘記正確設置它。更好的是避免所有的痛苦,只有在線程上進行文化特定的格式化,轉換等,才能保證您的文化設置正確無誤。

0

Windows總是初始化一個OS線程系統默認的LCID, 在區域和語言選項小程序配置的控制面板 英寸

不幸的是,我不得不不同意這一點,發現相反。

系統以美國英語安裝。 去控制面板改變一切爲丹麥語並複製到所有帳戶。 重新啓動。

運行控制檯應用程序它在丹麥運行。 運行web應用程序問瀏覽器它說丹麥語。 從網絡應用程序啓動線程,它啓動爲美國不丹麥,我不明白爲什麼。

0

我知道這個話題很古老,但我發現自己處於一個「操作系統文化」的問題。

我解決了這個問題:因爲BackgroundWorker是在一個UserControl中(如果它是在一個Form中,這將是有效的......)我在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); 
    }