2012-10-25 107 views
3

我有一個數據網格和計時器的窗體。 我已經創建資源CalculationSheet和DUTCH 翻譯 - 英國(默認) - 荷蘭語計時器耗盡資源全球化

我開始在荷蘭語中的應用。 當我選擇一個新的記錄消息框彈出窗口。 它顯示正確的語言,荷蘭語。 我也設置了計時器。

當計時器過去並再次顯示消息框時,資源將以默認語言顯示。

這裏是主入口點的應用程序:

/// <summary> 
/// The main entry point for the application. 
/// </summary> 
[STAThread] 
static void Main() 
{ 
    System.Threading.Thread.CurrentThread.CurrentUICulture = 
     new System.Globalization.CultureInfo("nl", true); 

    Application.EnableVisualStyles(); 
    Application.SetCompatibleTextRenderingDefault(false); 
    Application.Run(new Form1()); 
} 

這裏是回調代碼:

void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) 
{ 
    // shows in UK 
    MessageBox.Show(Properties.Resources.CalculationSheet); 
} 

private void Form1_Load(object sender, EventArgs e) 
{ 
    List<CalculationSheet> calculationSheets = new List<CalculationSheet>(); 

    calculationSheets.Add(new CalculationSheet("a")); 
    calculationSheets.Add(new CalculationSheet("b")); 
    calculationSheets.Add(new CalculationSheet("c")); 

    this.dataGridView1.DataSource = calculationSheets; 

    this.m_Timer = new System.Timers.Timer(); 
    this.m_Timer.Enabled = false; 
    this.m_Timer.Interval = 5000; 
    this.m_Timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed); 

    this.dataGridView1.SelectionChanged += new System.EventHandler(this.dataGridView1_SelectionChanged); 
} 

private void dataGridView1_SelectionChanged(object sender, EventArgs e) 
{ 
    // shows in DUTCH 
    MessageBox.Show(Properties.Resources.CalculationSheet); 
    this.m_Timer.Enabled = true; 
} 

回答

1

回調爲System.Timers.Timer class執行一個單獨的線程回調。

設置當Application.CurrentCulture property(或Thread.CurrentUICulture property)手動,它不流CultureInfo給創建的其他線程這就是爲什麼你會看到這個(CultureInfoExecutionContext跨線程流動);該回調在另一個線程上執行,並且未設置CultureInfo

這個測試用例表明CultureInfo.CurrentCulture沒有(未在Timer的回調,因此)流到其他線程:

[TestMethod] 
public void TestApplicationCurrentCultureInOtherThreads() 
{ 
    // Create the timer. 
    using (var t = new System.Timers.Timer(1000)) 
    { 
     // The task completion source. 
     var tcs = new TaskCompletionSource<object>(); 

     // Captured name. 
     CultureInfo capturedCulture = null; 

     // Set the current culture. 
     // The default for the system needs to be something other 
     // than "en-GB", mine is "en-US", which is why this 
     // test passes. 
     Thread.CurrentThread.CurrentUICulture = new CultureInfo("en-GB"); 

     // Copy t. 
     var tCopy = t; 

     // Event handler. 
     t.Elapsed += (s, e) => { 
      // Stop the timer. 
      tCopy.Stop(); 

      // What's the captured name. 
      capturedCulture = CultureInfo.CurrentCulture; 

      // Complete the task. 
      tcs.SetResult(null); 
     }; 

     // Start. 
     t.Start(); 

     // Wait. 
     tcs.Task.Wait(); 

     // Compare. 
     Assert.AreNotEqual(Thread.CurrentThread.CurrentUICulture, 
      capturedCulture); 
    } 
} 

回調不表示MessageBox.Show方法失敗的原因是它不需要消息循環(它提供了它自己的一個)並且可以安全地從任何線程調用。

如果可能,我會將您需要的CultureInfo存儲在應用程序中的一個位置,然後將其傳遞給其他線程上需要使用的任何方法(方法如String.Format)。

如果不可能,則必須在每個需要它的線程上設置Application.CurrentCulture。但要小心,如果在定時器回調線程上執行,這些線程來自線程池,因此您永遠不會知道線程池線程上的當前文化是什麼(因爲它未被重置)。

這就是說,如果你正在做UI工作在這些回調,那麼你真的應該通過對SynchronizationContext類的PostSend方法的調用元帥回調到UI線程(其中CultureInfo設置) (您可以將從UI線程調用的Current property的值存儲到其他線程的調用中)。

Form1_Load方法將存儲SynchronizationContext(它是創建窗體時設置):

private SynchronizationContext _synchronizationContext; 

private void Form1_Load(object sender, EventArgs e) 
{ 
    // Capture the context. 
    _synchronizationContext = SynchronizationContext.Current; 

    // Rest of code. 
    ... 
} 

然後你timer_Elapsed回調應該是這樣的:

void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) 
{ 
    // Marshal back to the UI thread. 
    _synchronizationContext.Send(s => { 
     // Will now show in Dutch, as this call is taking place 
     // on the UI thread. 
     MessageBox.Show(Properties.Resources.CalculationSheet); 
    }, null);  
} 
+0

感謝您的快速反應。 – user1773744

+0

@ user1773744 NP,我已經更新了更多的代碼,具體說明如何捕獲SynchronizationContext並將回調編組。 – casperOne