I want to otherwise block code execution on the main thread while still allowing UI changes to be displayed.
I tried to come up with a simplified example version of what I’m trying to do; and this is the best I could come up with. Obviously it doesn’t demonstrate the behavior I’m wanting or I wouldn’t be posting the question. I just hope it gives some code context to back my poor explanation of the problem I’m hoping to solve.
Within a button click handler on a form I have this:
private void button2_Click(object sender, EventArgs e) { AutoResetEvent autoResetEvent = new AutoResetEvent(false); new Thread(delegate() { // do something that takes a while. Thread.Sleep(1000); // Update UI w/BeginInvoke this.BeginInvoke(new ThreadStart( delegate() { this.Text = 'Working... 1'; this.Refresh(); Thread.Sleep(1000); // gimme a chance to see the new text })); // do something else that takes a while. Thread.Sleep(1000); // Update UI w/Invoke this.Invoke(new ThreadStart( delegate() { this.Text = 'Working... 2'; this.Refresh(); Thread.Sleep(1000); // gimme a chance to see the new text })); // do something else that takes a while. Thread.Sleep(1000); autoResetEvent.Set(); }).Start(); // I want the UI to update during this 4 seconds, even though I'm // blocking the mainthread if (autoResetEvent.WaitOne(4000, false)) { this.Text = 'Event Signalled'; } else { this.Text = 'Event Wait Timeout'; } Thread.Sleep(1000); // gimme a chance to see the new text this.Refresh(); }
If I didn’t set a timout on the WaitOne() the app would deadlock on the Invoke() call.
As to why I’d want to do this, I’ve been tasked with moving one subsystem of an app to do work in a background thread, but still have it block user’s workflow (the main thread) only sometimes and for certain types of work related to that subsystem only.
I went with something I haven’t seen posted yet which is to use MessageQueues.
Seems over the top considering the windows message loop already exists somewhere, but it works.