2013-03-04 73 views
2

我有一个带有eventhandler的MainWindow,它无法正常工作。我已经提出了这个问题的简单模型。请参阅代码注释中的问题是:事件不能正确提升

public partial class MainWindow : Window 
{ 
    public event EventHandler Event1; 

    public MainWindow() 
    { 
     Event1 += MainWindow_Event1; 
     InitializeComponent(); 
    } 

    void MainWindow_Event1(object sender, EventArgs e) 
    { 
     textBox1.Text = "wth!?"; //Not changing text box. Not showing message. If delete this line, it will work fine 
     MessageBox.Show("raised"); 
    } 

    private void bw_DoWork(object sender, DoWorkEventArgs e) 
    { 
     EventHandler evt = Event1; 
     while (true) 
     { 
      Thread.Sleep(500); 
      evt(null, null); 
     } 
    } 

    private void Button_Click_1(object sender, RoutedEventArgs e) 
    { 
     BackgroundWorker bw = new BackgroundWorker(); 
     bw.DoWork += bw_DoWork; 
     bw.RunWorkerAsync(); 

    } 

} 

请解释这种行为,我该如何解决它?

+0

也许当你进入你的事件时,你的文本框没有被初始化? – mlemay 2013-03-04 20:00:37

+0

你是什么意思,它工作正常,如果你删除该行? MessageBox显示?如果删除该行,预期的行为是文本框不会更改,那么工作正常意味着什么都不做? – evanmcdonnal 2013-03-04 20:00:57

+0

它应该抛出(在调试模式下)。跨线程和所有这一切。你真正的问题似乎是默默无视例外。 – 2013-03-04 20:01:29

回答

3

的问题是,您正在从后台线程调用该事件。这将无法正常工作,并且该程序在尝试访问TextBox时只是挂起。但是,如果您更改此代码:

textBox1.Text = "wth!?"; //Not changing text box. Not showing message. If delete this line, it will work fine 
MessageBox.Show("raised"); 

这样:

this.Dispatcher.BeginInvoke((Action)delegate() 
{ 
    textBox1.Text = "wth!?"; //Not changing text box. Not showing message. If delete this line, it will work fine 
    MessageBox.Show("raised"); 
}); 

它会为你工作。

+0

从线程访问控件时,程序不会“挂起”。 – 2013-03-04 20:03:33

+0

@HenkHolterman,对不起,我的道歉,让我重述一下。它不会执行设置文本框的行,并且不会继续到消息框。我想这只是堕胎? – 2013-03-04 20:07:22

+1

@MichaelPerrenoud感谢您的指导。但它应该是:this.Dispatcher.BeginInvoke((Action)delegate() { textBox1.Text =“wth”; MessageBox.Show(“raised”); }); – Dork 2013-03-04 20:22:42

1

这个问题,因为你需要使用当前线程的同步上下文线程间comunicating,一些这样的事

private void Button_Click(object sender, RoutedEventArgs e) 
    { 
     var sync = SynchronizationContext.Current; 
     BackgroundWorker w = new BackgroundWorker(); 
     w.DoWork+=(_, __)=> 
      { 
       //Do some delayed thing, that doesn't update the view 
       sync.Post(p => { /*Do things that update the view*/}, null); 
      }; 
     w.RunWorkerAsync(); 
    } 

请检查this问题,希望可以帮助...