2

I have a MainWindow with eventhandler which is not working properly. I have made simple model of this problem. Please see comment in code where the problem is:

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();

    }

}

Please explain this behavior and how can I fix it?

Dork
  • 1,816
  • 9
  • 29
  • 57

3 Answers3

3

The problem is that you're invoking the event from a background thread. This will not work and the program is simply hanging when trying to access the TextBox. However, if you change this code:

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

to this:

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"); 
});

it'll work for you.

Mike Perrenoud
  • 66,820
  • 29
  • 157
  • 232
  • A program won't 'hang' when you access a control from a thread. – H H Mar 04 '13 at 20:03
  • @HenkHolterman, right you are, my apologies, let me rephrase that. It will not execute the line that's setting the text box and further it will not continue to the message box. I guess that's just an abortion? – Mike Perrenoud Mar 04 '13 at 20:07
  • 1
    @MichaelPerrenoud Thanks for direction. But it should be: this.Dispatcher.BeginInvoke((Action)delegate() { textBox1.Text = "wth"; MessageBox.Show("raised"); }); – Dork Mar 04 '13 at 20:22
2

You can't update the UI elements from the background thread. The worker thread fails by exception trying to access the UI element (Text property). So messageBox isn't showing as well. Use notification mechanisms, or Dispatcher calls (there is a wast amount of information like this on the web)

Here are possible duplicates/help:

Update GUI using BackgroundWorker

Update GUI from background worker or event

Community
  • 1
  • 1
Sasha
  • 8,537
  • 4
  • 49
  • 76
1

This problem is because you need to use the Synchronization Context of the current Thread for comunicating between threads, some thing like this

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();
    }

Please check this question, hope can helps...

Community
  • 1
  • 1
Raúl Otaño
  • 4,640
  • 3
  • 31
  • 65