Consider i have a "Form" and it contains Button. I started the compiling process (Ctrl +F5). When i click the button the event is occurs and event handler is executed. Where does execution come back after event is handled?
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
//some Code
}
}
Short Answer: It goes back to listening for more events.
Detailed Answer:
Under the hood, everything in Windows runs on top of the Win32 API. The Win32 API has at least 2 functions that all programs run. The window procedure is one and that is where our event messages get processed. The other one is called the message loop and it looks similar to this:
while(GetMessage(&Msg, NULL, 0, 0) > 0)
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
return Msg.wParam;
The message loop is the heart of all event-based Windows programs. GetMessage() gets a message from your application's message queue. Any time the user moves the mouse, types on the keyboard, clicks on your window's menu, or does any number of other things, messages are generated by the system and entered into your program's message queue. By calling GetMessage() you are requesting the next available message to be removed from the queue and returned to you for processing.
TranslateMessage() does some additional processing on keyboard events. Finally DispatchMessage() sends the message out to the window that the message was sent to.
In every winforms application is "hidden" main message loop.
Main message loop is basicaly while(true) ... loop and checks for input (and some other) events like Click, KeyDown, etc...
This main loop is executed inside Application.Run(...) is call. Probably in your Program.cs file.
Check the Events overview for Windows Forms
When an event is recorded by the application, the control raises the event by invoking the delegate for that event. The delegate in turn calls the bound method. In the most common case (a multicast delegate) the delegate calls each bound method in the invocation list in turn, which provides a one-to-many notification. This strategy means that the control does not need to maintain a list of target objects for event notification—the delegate handles all registration and notification.
So the control itself, calls the delegate. The code of the control raised the method. So when you click the control there is some code in the control that calls the delegate you have provided.
The code commonly calls the delegate as it would any other function and continuous it's code flow:
i.e.
// do something
deletat(...);
// continue doing something
You can find an even better example here: Understanding events and event handlers in C#
on how delegates are being called.
Related
It was firs time I have used delegate and event. I made an error handler event for Memory Game program. The program has a "lot" of SQL operation. The event functioning wery well. I subscribe a MessageBox "caller void" to print errormessages out in the Main Form. (It was a surprise for me that I had to subscribe this printout void only in the Main and every Form errors are printed out by this little void.)
I have problem with error handling. When I handled the problems with Exceptions I could handle everything to the very end (if Exception not null do....).
Delegate and event is very usefull but I dont know how close the actual form or simply make something to do when an error happens.
I have tried to implement this.close() after MessageBox printed out the message but it closes the whole program.
private void MessageBoxPopUp(string errorMessageForMessageBox)
{
MessageBox.Show(errorMessageForMessageBox);
this.Close();
}
I would like to close the form parented by the main form or I want the program just do nothing. Now The messageBox ("Game saved succeddfully.") pops up after an error message because it is written under the void calling the errorMessage event. With Exception and braces I could separate the different derivations.
Thank you for help,
My understanding about events in C# for a console application:
create a delegate that has the same signature as the event handler method in the subscriber class.
declare an event based on this delegate
raise the event
My understanding of this step is: it is simply an wrapper function where parameters are passed to the event to invoke the event handler functions pointed to by the event.
So raising the event is just invoking the wrapper function in the publish class.
Now when I create a very simple Windows form application, I am not able to apply this general concept.
Consider a WinForms application with just one button.
// registering statement
Button1.Click += new EventHandler (this.button1_click)
I can identify the first step. It is the pre-defined System.EventHandler delegate.
Click event for the button is also pre-defined. No problem with that.
event raising step : here I fail to make the connection between a console application and an Windows application.
Where is the code kept that actually RAISES the event for a WinForms application? We don't seem to have to code it.
I understand click event is raised when someone "clicks" on the button, but how is that realized in the C# code for WinForms application?
How does the compiler "just" knows that a Click event for a button means someone clicking on a button and therefore an event should be raised?
How is click event raised? How are the parameters passed to the event?
The Control class has protected function called WndProc, when the OS needs to tell the program something it generates a Message object and passes it in to the WndProc function.
That WndProc function then looks at the message and sees what kind of message it is, if it is the "mouse left button up" message it runs the the OnClick method with the correct parameters parsed out of the Message object that was passed in to WndProc.
That OnClick method is the thing that raises the event to the subscriber.
From the soruce of .NET:
The entry point of WndProc
It detecting the message type
It parsing and calling the OnClick method
It raising the Click event
Your understanding is a bit backwards. I think this is why you have issues.
You are not creating a delegate that has the same signature as the event handler method in the subscriber class.
What you are doing is declaring what a function to which to delegate execution will look like. Here is the signature for EventHandler:
public delegate void EventHandler(object sender, EventArgs e)
So, if you want a function to be able to handle delegation of the event, it must follow that signature.
Now, the class that will delegate execution to subscribers needs a reference to those functions so it can call them when the event takes place. That is why you implement an event property. It follows then that the Button class must expose this property for you to be able to "hook" your delegates:
public event EventHandler Click
(Notice this is inherited from Control)
When you register an "event handler":
Button1.Click += new EventHandler (this.button1_click)
You are essentially saying that you want this.button1_click(object sender, EventArgs e) to fire whenever the Click event is raised by the Button1 instance.
The Button1 instance will internally decide when to fire the event at which point it will use the event property to delegate execution to the subscribed functions. It will call them with the above mentioned parameters where sender will most likely be the instance itself and the EventArgs class will give you additional information about the conditions that raised the event. The property is also usually implemented to add additional checks (like if there is anything to call in the first place).
As you can see, the code that actually raises the click is internal to the implementation of the Button (or its inheritance chain). It obviously involves mouse tracking and what not, which is the benefit of using the controls by the way, unless you want to write all that detection stuff from scratch.
I am listening the port and Once I receive the message doing some of processing than inserting into the database. All good so far.
The issue is that into the method of port_received I'd like to popup the form of showing that the device received message and depends user click the OK and seeing the message. And at the background of the popup form there is a timer and closing the form in 2 sec unless user doesnt click the button of see the message.
I am calling the form than .ShowDialog() after that I am loosing my serial port communication.
If I use .Show() I cannot see the properly
some of code:
private void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
data = comport.ReadLine();
ReceiveMessagePopup popUp = new ReceiveMessagePopup(data);
popUp.Location = new Point(150, 150);
popUp.ShowDialog();
/// after that code I cannot do anything even cannot show any MessageBox.
}
I would not put a ShowDialog or any other UI management in that method as it can be raised many times as soon as data is received.
I think that event handler should just receive and store the data somewhere and the ShowDialog or other notification or UI handling should be done out of that method.
see here for examples on how to use with that event handler and save the incoming data:
How do I use dataReceived event of the SerialPort Port Object in C#?
From the MSDN article on SerialPort.DataReceived
"The DataReceived event is raised on a secondary thread when data is received from the SerialPort object. Because this event is raised on a secondary thread, and not the main thread, attempting to modify some elements in the main thread, such as UI elements, could raise a threading exception. If it is necessary to modify elements in the main Form or Control, post change requests back using Invoke, which will do the work on the proper thread."
Use Control.BeginInvoke to execute code on the main UI thread to show the dialog. e.g.
assuming this code is in a class that inherits from Form
var data = comport.ReadLine();
_buffer.Append(data);
if (_buffer.IsValid)
{
BeginInvoke((Action) (() =>
{
ReceiveMessagePopup popUp = new ReceiveMessagePopup(buffer);
popUp.Location = new Point(150, 150);
popUp.ShowDialog();
}));
}
You don't want to do long running tasks in the event, and as Davide points out, showing the dialog every time the event is raised is probably not a good idea, as you may get many events raised, even for a single line of data from the serial port, so that's why I would add the data read from the port to a buffer, and if the buffer is valid (e.g. contains a whole line/message/packet/whatever) then show the dialog
I have a form that appears as shown in the attached image. I have two parts of the form that concern this question: the TabControl, and the Panel, as shown in the image. It should be noted that the panel is NOT within the TabControl.
My situation is that I have a thread that executes continuously when the button, displayed in melt-your-eyes green in the Panel, is clicked. The thread polls the device which I'm interfacing with and updates the controls in the "Status" GroupBox at the bottom of the TabControl. When the user clicks on a control in the TabControl (tabControl_Enter event), I trigger a ManualResetEvent which lets the thread finish its iteration so that I can perform the IO required by the clicked control. The code to to suspend the thread is as follows:
private void StopSynchThread()
{
synchWaitHandle.Reset();
//various UI changes
}
private void updateSynchStat()
{
while (true)
{
synchWaitHandle.WaitOne();
try
{
updateSynch();
}
}
What I would like to do is then restart the thread automatically, instead of by button press, as is currently done. What I'm trying to do is avoid having to restart the thread by conditionally calling StartSynchThread() within each of the "bazillion" UI event handlers. StartSynchThread() is defined as:
private void StartSynchThread()
{
synchWaitHandle.Set();
}
Is there a precedent or decent paradigm for handling this? Without any concept of how to do so, I was thinking that I could alter my function that performs the IO with the device to generate an event after it gets a response from the device, but that seems inelegant.
Any ideas? I appreciate your insights. Thanks.
If you really can fire it off with a simple button click, you ought to be able to just put a timer on the form that will periodically check for the right conditions and then "push" the button (call synchWaitHandle.Set();) automatically.
I have a problem that I have found many similar problems related to multi threading, but noone linked to me specific problem.
I have a method that does something, but when the method has been called, I don't want it to return untill a button is clicked.
So basically, at the end of the method, I would like it to stay put and wait for the Button_Click event to finish, and then the event should in some way "tell" the method to continue.
Currently I have done this by adding a loop at the end of the method like this:
while(someVariable){
Thread.Sleep(10);
Application.DoEvents();
}
Then the Button_Click event set someVariable to be false, and then the loop stops.
Of course, this looks very "iffy", and having this loop run every 10 milliseconds seems like a gigantic waste.
Are there any way of doing this properly? Since the method in question runs on the same thread as the rest of the application, it's also important that halting the method does not block the tread for other activities.
The reason I need this is because when the method is called from somewhere else, this method will draw up some components (including two buttons). Then the user clicks one of them, and then the method will return a different value depending on which button was clicked, and the program calling it can't continue untill it knows which button was clicked. So my program will look like this.
....
if( someMethod() == ButtonA ){
//do the proper action if button 1 is clicked
}else{
//do the proper action if button 2 is clicked
}
I hope this was not to confusing.
Assuming this is in the UI thread, you absolutely should not do this. You say "it's important that halting the method does not block the thread for other activities" - that basically means you need to find a different design. If the UI thread is "staying put and waiting for the Button_Click event to finish" then it can't be doing anything else without using the hack of Application.DoEvents().
Instead, you should make a call back to the original caller when the event occurs. Either expose an event that the caller can subscribe to, and raise that event when the button click finishes, or get the caller to pass in a delegate to call appropriately. (They're equivalent really, just different ways of propagating the callback.)
That's the way WinForms (and other rich client UIs) are designed to work - on an event-based model, basically.
Use AutoResetEvent, see sample and documentation at http://msdn.microsoft.com/en-us/library/58195swd.aspx
Your main thread does a WaitOne() on the event and in you Button.Click event, you Set() the event.