• 0

[C#] Updating a label in real-time without deadlocking form


Question

I have a while loop that updates the form, while the actual information for the form is updated in a separate thread. The problem is, it is designed like this currently:

		while (!quit) {
			this.SuspendLayout();
			this.BeginInvoke(new InvokeDelegate(UpdateForm));
			System.Threading.Thread.Sleep(1000);
			this.Update();
			this.ResumeLayout(true);
		}

UpdateForm just updates the Text properties of 2 labels and exits. I've tried a lot in the past few hours, but this while loop thing has got me... How do I prevent such a deadlock? I've tried various combinations of Threads, Invoke, BeginInvoke, and the like, and nothing has worked. I've went through several tutorials on the topics (all of which dealt with the console), and understood how things worked. I even created my own console app based on what I learned. Windows Forms is a completely different animal from console apps though... Can anybody help or provide suggestions? Note that this isn't homework (I can't imagine doing this for homework...); it is just being done in the pursuit of knowledge! :)

4 answers to this question

Recommended Posts

  • 0

Here, I am assuming the child thread is doing some job X.

The BeginInvoke code, should be called from within the child thread context, and not from within the main thread (which handles the UI). You don't need a while loop in the main thread to update the UI.

edit---

Something like this:

public class ThreadExample : Form {
	// The ThreadProc method is called when the thread starts.
	// It loops ten times, writing to the console and yielding 
	// the rest of its time slice each time, and then ends.
	public void ThreadProc() {
		for (int i = 0; i < 10; i++) {
			Console.WriteLine("ThreadProc: {0}", i);
			// Yield the rest of the time slice.
			Thread.Sleep(0);
			// do job X
			this.BeginInvoke(new InvokeDelegate(UpdateForm)); // update UI
		}
	}

	private void UpdateForm() {
	  // do form updating here
	}

	public ThreadExample() {
		Thread t = new Thread(new ThreadStart(ThreadProc));
		t.Start();
	}
}

Edited by g0wg
  • 0

Thanks, g0wg. After some manipulation, I was able to adapt it to my form. All of my ideas centered around using the main thread to update the UI while having a worker thread do its job that the UI relies on. You made it simple to understand - call BeginInvoke on the separate thread to update the UI, not the main thread. Thank you very much! :)

  • 0
  rpgfan said:
Thanks, g0wg. After some manipulation, I was able to adapt it to my form. All of my ideas centered around using the main thread to update the UI while having a worker thread do its job that the UI relies on. You made it simple to understand - call BeginInvoke on the separate thread to update the UI, not the main thread. Thank you very much! :)

You should probably learn why your previous attempt failed, too.

The Invoke() and BeginInvoke() methods work by posting a message to the UI thread of the control you call it on (the thread that owns the window and contains its message loop). Since you're calling this function from the UI thread, that message is sitting in the message queue for the thread you're currently running on. And since you are blocking that thread with your loop, its message loop will never be called and the message telling it to invoke your UpdateForm command will never be processed. In fact, you're just going to sit there filling up the message queue forever.

If you're new to Windows or UI programming, you should take the time to learn how windows (not Windows the OS, but "windows" the programming concept) work. Understanding window messages / window processes may not strictly be necessary for simple .NET programming, but it can certainly help prevent mistakes like this one.

  • 0
  Brandon Live said:
You should probably learn why your previous attempt failed, too.

The Invoke() and BeginInvoke() methods work by posting a message to the UI thread of the control you call it on (the thread that owns the window and contains its message loop). Since you're calling this function from the UI thread, that message is sitting in the message queue for the thread you're currently running on. And since you are blocking that thread with your loop, its message loop will never be called and the message telling it to invoke your UpdateForm command will never be processed. In fact, you're just going to sit there filling up the message queue forever.

If you're new to Windows or UI programming, you should take the time to learn how windows (not Windows the OS, but "windows" the programming concept) work. Understanding window messages / window processes may not strictly be necessary for simple .NET programming, but it can certainly help prevent mistakes like this one.

Thanks for the explanation, Brandon. Actually, I'm pretty decent at event-driven programming. I just wasn't thinking in an event-driven manner. I was doing too much object-oriented thinking (<sarcasm>because OOP solves all problems, right?</sarcasm> :)) and not enough intelligent thinking to realize that I was missing something so obvious. I am indeed new to UI programming, and that is probably another major reason why I didn't get it. I'm glad it was something fairly simple to resolve. Again, thanks to all that helped.

This topic is now closed to further replies.
  • Recently Browsing   0 members

    • No registered users viewing this page.