5

I'm really embarrassed to ask such a trivial question but debugging some software now convinced me I don't really understand this issue:

How does .NET events work seen from an altitude of 20,000 feet? I don't mean the delegate/event handler pattern and all this. What I mean is - what's the BIG picture:

  1. Code A is doing something.
  2. Some external trigger happens. Say, for example, that the user clicked on some control.
  3. A magic happens and the event handler for the event is called.
  4. another magic happens after the event handler returns.

Now, what is the magic? How does this relate to threads? Is the thread running my code interrupted when the event occurs, and then resumes after the event handler return? But I googled and found out that .NET handlers are called synchronously in the original thread. So who takes care of stopping and resuming Code A? What happens if events are nested (i.e. Event 2 happens when the event handler for Event 1 is running)?

Edit: As far as I understand the answers say that the event hander for the next event will run only after the currently running event handler finishes. This means that your code is not interrupted: line n will always run immediately just after line n-1 and just before line n+1. However just before I posted the question I was debugging a program controlling, through automation, Internet Explorer (using SWExplorerAutomation from Webius). I'm quite sure that as I was line-stepping through the code I was "kidnapped" :-) to some event handler and returned to the interrupted position in the code once that event handler finished its business. This means that either do not understand the answers, or that the program behaves differently while being stepped through the debugger!

3 Answers 3

3

Let me shed some light on your problem. The magic is the windows message loop. You see in your example, actually, there is nothing making Code A stop when an event occurs. Rather, this is the sequence.

When code A is running, the user clicks on a button. The button's window message gets queued, but nothing happens. When code A exits its function or relinquishes control back to the message loop, then the Click event is processed and the Event Handler is run.

Try this experiment. Put an infinity loop inside your program on the main thread and then click on the user interface. You will notice that the user interface will be unresponsive and there will be no Event Handlers running.

Sign up to request clarification or add additional context in comments.

2 Comments

This is true for WinForms applications, but don't forget the more general case, where no message pump is involved. In this case, everything runs synchronously without a mitigator, and there is no magic involved.
@bzim I understand the good old mulit-mailboxes, wake-me-up-when-a-message-arrives-if-I'm-with-a-higher-priority-than-the-currently-running-task model such as in good old Intel's RMX. What I don't understand is Windows's sleight of hand model.
2

The thing you will see from 20,000 feet is the MessageLoop. It is inside Application.Run().

Simply stated, this is a while-loop that runs the entire lifetime of your app and does

 // pseudo code, I did not reflector Application.Run while (GetMessage(ref msg) { DispatchMessage(ref msg); } 

You will notice the simgle-thread when you take too long handling 1 event, your app will be labeled 'nonresponsive' in TaskManager.

A related method is Application.DoEvents(), but stay away from that.

2 Comments

This is true for WinForms applications, but don't forget the more general case, where no message pump is involved. In this case, everything runs synchronously without a mitigator, and there is no magic involved.
bzim, I reacted to the example of the Control-click. You are right in general but I think the OP is thinking about WinForms.
1

Events are pointers to functions (just like we used to have in C++). When you use plain vanilla .NET event you're actually calling the functions that are connected using += to that event. So from 20,000 feet your code actually calls some other code just like calling another function. This is why it's called synchronously and in the same thread.

When inside WinForms/WPF control we also have a message loop to consider: All events that occurs within the context of the form adds a message to the message loop instead of calling a method directly.

The main thread of the control polls that loop for new messages and when a new message appears he executes it (again in the main thread) only now it's not exactly synchronous.

This is the reason that if a form is busy doing something and you press a button it takes some time before that button is pressed. this is also the reason that if you invalidate a control it's appearance is only changed after you exit the running method (and the next message is processed).

3 Comments

0. Thank you for your answer :-) 1. Are you saying that EACH control (button, label, list-box etc.) on a form has its own message loop and its own thread? And each HTML control inside a web page? This seems really wasteful. 2. I did not understand the whole section starting with "This is the reason...". Could you explain?
1. If I remember correctly Each main window has it's own message loop - not each control 2. The message loop is the reason that calls in the same thread are not synchronous - i.e. pressing a button don't cause the button press event to fire intermediately but it runs in the context of the main thread.
Dror, not every Window, every Application. And while you can start a second one that is very rare.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.