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.
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 writing a C# program, which uses the UI Automation via Com interop. However, I am having a problem adding/removing an event handler from within another event handler:
My program starts up a new MTA thread, and on that thread, calls AddFocusChangedEventHandler().
I want to monitor for property changes on the focused element. So within the focus-changed handler, I call RemovePropertyChangedEventHandler() on the previously focused element, and AddPropertyChangedEventHandler() on the newly focused element.
However, I find that after about two focus changes, I stop getting either focus-changed, or property-changed, events. My hunch is that something is blocking the background thread.
If I remove the property-changed code, then just the focus tracking works just as expected.
I'm not sure if this is pertenant - but the documentation states that event handlers should be added/removed on the same thread. Since I'm calling AddPropertyChangedEventHandler() in one focus-changed event, and RemovePropertyChangedEventHandler() in another focus-changed event, it's possible that the two calls are being executed on different threads. However, I doubt this to be the case - and even if it were, it shouldn't exhibit the blocking behavior I see. Just mentioning it here for completeness.
There may be multiple problems here. But it's worth noting that after you RemovePropertyChangedEventHandler, you may still get some more events if there are multiple events on the same item (you'll for example get multiple child_added structure changed events if there are multiple children added to an item, it may be similar with multiple properties changing - but not sure). So, if you get multiple events, your code will be called multiple times, probably messing things up.
Another issue is, as you've pointed, you shouldn't subscribe / unsubscribe to events from different threads. But I think this is relevant when there's a chance that these actions are not synchronized - if you're subscribing and unsubscribing to different events (likely in your case) then things will get messy - I'll hazard to say that if you do the subs/unsubs in sequence by some lock mechanism then it should be fine.
As I understand it, one of the main causes of memory leaks in C# is failing to unregister event listeners when its container is disposed. For this reason, whenever I manually register an event - such as a Timer.Elapsed += ... - I make sure to Timer.Elapsed -= ... when I am done with the object (or parent object).
However, I was just looking over a Windows Form Designer generated class, and noticed that while it happily subscribes to events (e.g. this.button1.Click += new System.EventHandler(this.button1_Click);), it seems there is no cleanup procedure other than the default components.Dispose(); action.
Does this mean the Dispose() method of each component is expected to unregister/unsubscribe from any events that have been bound to it; if so, how does the component unregister from 'external' event handlers it is not aware of, and does this mean that manual attempts to remove event listeners from standard [IDisposable] Windows controls (timers, buttons, forms, etc.) is generally unnecessary?
Thanks
Event handlers only cause memory leaks if the object containing the event lives longer than the object containing the handler.
In a typical WinForms scenario, both the controls and the form code only live as long as the form is opened, so there is no problem in the first place.
You only need to unregister your handlers from static events, singletons, or other long-lived objects.
Good design, mostly. The object model was well-crafted to ensure that the event source can't outlive the subscriber. There certainly is a circular reference, the form keep a reference to the control through its Controls collection as well as a possible private variable, the control adds a reference to the form through an event subscription. But the control's lifetime is controlled by the form, both go poof when the user closes the window. That removes the usual one-and-only reference to the form object, kept in an internal table that maps a Handle to a Form. The GC has no trouble with the circular references.
There are a handful of sharp edges, the Application.Idle and the SystemEvents events are trouble. They have plenty of yellow tape in the MSDN Library.
Disposal is automatic as well, not used to unsubscribe events in Winforms, every control disposes the references in its own Controls collection. That starts at the Form class and iterates through the tree automatically. Overriding the form's Dispose() method is unusual, also tends to cause lots of angst because that method is present in the form's Designer.cs file. Moving that method is fine, as is using the FormClosed event to dispose as an alternative.
That has a sharp edge with the byte of a chainsaw though. Disposing controls is not optional in Winforms. Very unusual, it is optional everywhere else in the framework, the finalizer backs-up forgetting to call it. Not in Winforms, if you use Controls.Clear or Remove then the control you remove is not disposed. It is rehosted to a hidden window called the "parking window". Keeping the control alive to move it to another parent. Nice feature, except when you don't move it elsewhere. It will live on that hidden window forever, very nasty leak. Not good design.
There are patterns to solve the lifetime problem for events. The "weak event pattern" is fairly boilerplate in .NET programming today. It is a bat-signal sign of an design problem, typically induced by liking the observer pattern because it works so well in .NET but not liking the contract that comes with it. An overbearing object model is almost always the root of the problem, like the three letter acronym whose Name Shall Not Be Mentioned in the [winforms] tag :)
The event source will keep the subscriber around not the other way. When the form goes away it will be eligible for GC which will inturn make the listeners eligible.
I have a solutions where three projects are running. One of my project is class library that is isolated from other two class. Now what I want to do is to load it into existing appdomain and auto execute its methods on some event occured from other assemblies in same domain.
I have an event inside that, and i want to execute that event
Is it possible? I not getting the way to autoexecute an. While googling I fouund AppDomain.CreateInstance () but not able to fully utilise it.
OR
Way to trap events occuring in APPDOMAIN. Since i have my dll loaded in domain so how can I trap events occuring inside a domain.
It's reasonably straight forward, this should get you going:
http://msdn.microsoft.com/en-us/library/ms173139(VS.80).aspx
Basically you need to create an object that inherits from MarshalByRefObject, then pass an instance of it to the parent Appdomain. You now have an object running in your appdomain that you can manipulate, be it attaching or raising events, calling methods, whatever.
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.