【问题标题】:Event not raising properly in forms事件未在表单中正确引发
【发布时间】:2013-03-04 19:57:34
【问题描述】:

我有一个带有事件处理程序的 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();

    }

}

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

【问题讨论】:

  • 也许你的文本框在你进入你的活动时没有初始化?
  • 去掉那一行是什么意思?显示消息框?如果删除该行,预期的行为是文本框不会改变,所以正常工作意味着什么都不做?
  • 它应该抛出(在调试模式下)。交叉线程和所有这些。您真正的问题似乎是默默地忽略异常。
  • @evanmcdonnal 它将每 0.5 秒显示一次消息
  • @mlemay 文本框没问题,我可以从其他地方更改它的文本,例如来自 Button_Click_1

标签: c# .net wpf multithreading events


【解决方案1】:

问题是您正在从后台线程调用事件。这将不起作用,并且在尝试访问 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"); 
});

它会为你工作。

【讨论】:

  • 当您从线程访问控件时,程序不会“挂起”。
  • @HenkHolterman,你是对的,我很抱歉,让我改写一下。它不会执行设置文本框的行,并且不会继续到消息框。我猜那只是堕胎?
  • @MichaelPerrenoud 感谢您的指导。但应该是:this.Dispatcher.BeginInvoke((Action)delegate() { textBox1.Text = "wth"; MessageBox.Show("raised"); });
【解决方案2】:

您无法从后台线程更新 UI 元素。 工作线程在尝试访问 UI 元素(Text 属性)时因异常而失败。所以 messageBox 也没有显示出来。使用通知机制或 Dispatcher 调用(网络上存在大量此类信息)

以下是可能的重复项/帮助:

Update GUI using BackgroundWorker

Update GUI from background worker or event

【讨论】:

    【解决方案3】:

    这个问题是因为你需要使用当前线程的同步上下文来进行线程之间的通信,像这样

    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问题,希望对您有所帮助...

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-09-04
      • 2015-03-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多