2012-10-25 144 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