I'm working on a bug where code is not always being executed before an application shuts down. The code was in a handler for the AppDomain.CurrentDomain.DomainUnload event.
I found a post by someone with the same problem who received this advice
"By the time the DomainUnload event happens for your default app domain, your
code has stopped executing. You can probably do what you need to with the
ProcessExit event on the default AppDomain."
This worked for me but I would like to know why. I haven't been able to find much on either of these events or on the differences between them. I'm also wondering if I need to subscribe to both or is the ProcessExit sufficient.
EDIT:
I wanted to add more information to make this a little more useful.
I left out that new threads were being created in their own AppDomain. Since I wanted this code to run not only when the parent process was done but also when each thread finished I needed to subscribe to the DomainUnload event to handle when each thread finished and also the ProcessExit event to catch when the parent process finished.
ProcessExit should be sufficient.
The DomainUnload event is designed to be handled by other AppDomains, not the AppDomain being unloaded. As a result, if the handler is attached in the domain being unloaded, it might not run. The ProcessExit event is designed to run when the process is going to exit.
Related
There is an issue that makes me curious about for quite some time.
Assume this scenario:
You created a program in C#, which has some classes inwhich you defined some events,
and other classes consume those events - they implement event handler methods for them.
My question:
What are the CLR's "rules" for running the event handler(s), for cases where events happen simultaneously?
If one event handler is running, and another event was raised now, will the CLR let the current event handler finish, and then just go to the next event handler? (the "second" event might be a second raise of the same event, or a different event)
Or is there a case where the CLR pauses the current event handler due to an event that came in the middle, then runs the second event handler, and then resumes back to the middle of the first event handler that was left?
Any info or article that makes an order in this, will be greatly appreciated.
BTW:
For this question, please assume 2 possible situations:
1) The classes with the events and event handlers are not Controls
(simple classes that you write, that inherit type object and not type Control)
2) The classes with the events and event handlers are inheriting class Control (Windows Forms)
I mention this because maybe the behavior/rules are different between the two.
Also, I would be grateful if you can relate to following things, that might affect the answers to these 2 questions:
- Application.DoEvents() method
- Timers
- any other class/method like this that might give different results beyond the simple ones that we might think of in the "normal" case..
Thank you
This has nothing to do with the CLR or the language. It's purely based on the specific implementation of the class defining the method. It can be written such that it fires of the event while handlers for a previous invocation are still running, or it could not. If you're dealing with a winforms program then most object firing events are firing them in the UI thread, so since there is only one thread that can be firing the events it can't ever fire them while other handlers are still running, but there are other objects that aren't forcing their usage to a single thread and as such can fire an event while handlers for a previous invocation are still running.
So all you can really do is look at the documentation/source code or do some experimental tests to see what any particular class does, or be safe and assume the worst case. There is no general case answer.
I am facing a problem that Application.DoEvents() can solve. The problem is that WebBrowser suppose to navigate to a url asnychronously but it does't, and when I use Application.DoEvents() it solves that, I think this happens because the application handles some other events and doesn't deliver the events of the navigation properly.
I read a little about this method and I understand that method will cause the application to handle all the currents events. Now I am a bit concern because I used a cannon to kill an ant, Can someone tell me if what I did is worthwhile?
Yes, Application.DoEvents() solves this problem. The core issue is that WebBrowser is a heavily threaded component at its core. You can call its Navigate() method and it goes off doing its stuff without blocking your code, the method returns almost immediately.
The problem however is that at some point it has to run your DocumentCompleted event. Which is guaranteed to run on the thread on which you created the browser object. That's hard to do, your thread may well be busy doing something else. Like sitting in a loop, testing the ReadyState property. There is no mechanism to interrupt this loop and run the event handler.
So what you see is that the ReadyState property never changes and the DocumentCompleted event never fires. This is called deadlock, a very common curse of threaded code. Using DoEvents is the back-door, that "pumps the message loop". It allows the browser to break into your thread and fire the event. Which in turn updates the ReadyState property and lets you break out of the loop.
There's a Big Problem with DoEvents however. it isn't selective, it doesn't just limit itself to handling the message that allows the event to fire. It also dispatches other notifications, the kind that will crash your program. Like your user getting impatient with the slow web site and closing your form. That destroys the browser object but does not stop your loop. You are now testing the ReadyState property of a disposed browser. Kaboom!
You'll need to do this differently. It is never legal to block or hang up the UI thread in a loop, it is very prone to create deadlock. It is in fact forbidden by Microsoft guidelines for an STA thread. The workaround is simple, move whatever code you now have after the wait loop to the DocumentCompleted event handler. You might need to add some state variables to your class so that you know that the event signals completion of a particular web page or that the user is no longer interested in the result.
The Application.Dovents() method makes all pending messages processed. That can cause:
Entering a code block twice before the current one finishes. (Let's assume that you navigate your browser with a button click. User clicks the button and while your code is waiting browser to copmlete the user clicked again. In that case Application.Doevents() will cause processing that method before stepping next line.)
Interrupting critical codes. (Lets assume that you have a time consuming method and the user clicked close button. Your form will disappear but your code will continue to run. A real problem.
Many more UnExpected results.
However I feel sometimes using this method is necessary and an easy solution like webbrowser which is difficult to use in multithreading (especially when its visible). If you have to use this method you should be sure that user and other things (timers, buttons, events vs) don't interrupt anything.
For a detailed discuss:Use of Application.DoEvents()
The scenario is an event on a buffer, that informs interested classes when there is data available to be collected. The event is fired as soon as new data is written to the buffer. When this is fired, the delegate for the event (in the interested class) starts reading data from the buffer.
My question is, if the event were fired again (before the method had finished reading all the data from the buffer) would the reading method be 'reset' or would the event wait for the method to finish reading the data before calling it again?
The event could only be fired again before the method had finished reading if it were fired on another thread. The event handlers will then (by default) be called again in that separate thread. There's no concept of an existing method being "reset", nor would it wait for the already-running handlers to finish before firing again.
Of course, you could potentially change how the handlers work, or how the event is fired - perhaps ensuring that the event handlers are only called from a single thread, with some sort of queue of events. It's impossible for us to tell whether that's appropriate for your situation though.
Neither, it would execute it alongside (in parallel), if on separate threads - otherwise execution would be blocking anyway.
Unless you've put Application.DoEvents() in your code (which is a horrible thing to do) then your event won't be interrupted.
In a multithreading scenario, there's the possibility of them running in parallel. I don't use multiple threads and events both at the same time, so I can't really say much about that, but it seems like Jon's covered that one nicely with his answer.
I am having a lot of trouble with AppDomains. I currently have an AppDomain containing camera controls, and am trying to have events raised from this secondary AppDomain (like a picture being taken) come back to the main program. Everything seems to be set up correctly (events are registered, functions will run across domain boundry) but when I try to invoke, nothing happens. Everything I can find on the subject involves exceptions being raised rather than just nothing happening at all.
I don't know how much better I can explain it than this, so I made a (very simplistic) diagram, and can post any code that is necessary.
http://a.imageshack.us/img832/8205/cameradiagram.png
A breakpoint fires in the OnPictureUpdated.Invoke(pic); portion, inside the secondary AppDomain, but nothing (either inside CameraContainer or in the main application is raised. I am doing a null check when invoking events, I just didn't put that in the diagram.
+1 for the effort in the question.
I believe this may just be because your CameraContainer isn't a MarshalByRefObject. Because it's attaching to the event, the AppDomain containing the CameraManager effectively needs to call back into the primary AppDomain when the event is raised.
Say I have an event with 2 subscribers (everything occurs in the same thread) - one subscriber writes to a log file, the other shows a MessageBox.
If the MessageBox is the first on the subscription list, then the log entry is not written until the after the user closes the message box. So the time in the log entry will really be the time the message box was closed, not the time the event occurred.
It seems the best solution is to have the log writer subscribe to the event before the code that displays the message box. However, in a similiar question here: Are event subscribers called in order of subscription?
the best answer was to never rely on the order of the subscribers. So how do I prevent the conflict without worrying about their order?
All of the individual event subscribers need to play well with others. The proper thing is for the event that shows the MessageBox to launch a background thread and show the MessageBox from there.
According to the documentation on events in the MSDN C# programming guide, events have the following properties (key point is bold):
The publisher determines when an event is raised; the subscribers determine what action is taken in response to the event.
An event can have multiple subscribers. A subscriber can handle multiple events from multiple publishers.
Events that have no subscribers are never raised.
Events are typically used to signal user actions such as button clicks or menu selections in graphical user interfaces.
When an event has multiple subscribers, the event handlers are invoked synchronously when an event is raised. To invoke events asynchronously, see Calling Synchronous Methods Asynchronously.
Events can be used to synchronize threads.
In the .NET Framework class library, events are based on the EventHandler delegate and the EventArgs base class.
Looks like the best bet is to use BeginInvoke on the events.
EDITED:
Are you in control of the event code? If so, you can make sure it's never implemented in a pathologically weird way which reorders things. You can even document that as part of the event itself: "Handlers to this event are always called in subscription order, synchronously."
To be honest, I'd really expect any event which didn't go along with that to explicitly document it.