TomPearson

I have what may seem like a silly question, but hopefully someone can let me know.

If I have 3 objects, which I will call A1, A2 and A3, that all reference each other (I have a data model that is effectively a graph structure that I am modeling) and each attach to an event on a different type of object, which I will call X, so that when something happens they can all react accordingly.

My question is as follows.

1 The event fires on object X

2 The handler on A1 responds to the event as a result it causes all references to A2 and A3 to be removed, effectively deleting the 2 objects.

3. What happens now

Does the invokation list of the event on object X realise that objects A2 and A3 have gone and not try and invoke them

or does the fact that it has a refence to the handler mean the objects persist

or will it try an invoke something on an object that may have been garbaged collected

Alternatively...

Am I using events where I shouldn't be

Is there a way to unhook events that I am missing

Cheers
Tom



Re: Visual C# General Events and Handlers

TomPearson

I have what may seem like a silly question, but hopefully someone can let me know.

If I have 3 objects, which I will call A1, A2 and A3, that all reference each other (I have a data model that is effectively a graph structure that I am modeling) and each attach to an event on a different type of object, which I will call X, so that when something happens they can all react accordingly.

My question is as follows.

1 The event fires on object X

2 The handler on A1 responds to the event as a result it causes all references to A2 and A3 to be removed, effectively deleting the 2 objects.

3. What happens now

Does the invokation list of the event on object X realise that objects A2 and A3 have gone and not try and invoke them

or does the fact that it has a refence to the handler mean the objects persist

or will it try an invoke something on an object that may have been garbaged collected

Alternatively...

Am I using events where I shouldn't be

Is there a way to unhook events that I am missing

Cheers
Tom





Re: Visual C# General Events and Handlers

Rob Teixeira

I'm not sure what you mean by step 2... deleting the objects CLR objects cannot be really "deleted" until the garbage collector removes them from memory. If you remove references to the object, it just floats in memory in an "unreachable" state until the next garbage collection cycle. Unless you also specifically remove their references from the invocation list, the multicast delegate still has valid references to those objects and will continue to call their handler methods. However, you cannot guarantee the order of the invocation list (which object gets notified of the event first, for example).

If the multicast delegate has a hard reference to the handler, and something in use in turn has a hard reference to the multicast delegate, the handler's object is still reachable, so it will not be deleted by the garbage collector.

It might help to understand exactly what you are trying to accomplish before I can give you a recommendation.





Re: Visual C# General Events and Handlers

artgillespie

To unsubscribe from an event, use '-=' in the same way you use '+=' to subscribe to it.

Code Snippet

instanceOfX.SomeEvent += A1.SomeEventHandler;

instanceOfX.SomeEvent += A2.SomeEventHandler;

instanceOfX.SomeEvent += A3.SomeEventhandler;

//when you remove all references to A2 and A3 in A1's event handler, just call

instanceOfX.SomeEvent -= A2.SomeEventHandler;

instanceOfX.SomeEvent -= A3.SomeEventHandler;

Unfortunately for your needs, in my tests here if you do that from within A1's handler, A2 and A3 will still get called for the current event. They are removed for the next time the event is raised. The only way I figured out how to do what you want is to throw an exception in A1's handler and have a try/catch block around the code that raises the event in X.

Code Snippet

//somewhere in code called from A1's handler:

instanceOfX.SomeEvent -= A2.SomeEventHandler;

instanceOfX.SomeEvent -= A3.SomeEventHandler;

throw new StopEventException(); //custom exception--A2 and A3 are never called

//in the code that raises SomeEvent in X:

try

{

SomeEvent();

}

catch ( StopEventException e ) {}

This keeps A2 and A3 from executing during the event dispatch.

Hope that helps! Great question... had fun investigating. Smile

Art





Re: Visual C# General Events and Handlers

TomPearson

As your investigation has shown (glad you enjoyed it) the handlers still get called unless I throw an exception, which unfortunately breaks the flow through my data graph as I cannot guarentee that there will not be other obejcts needing to respond to the event - most likely unreferenced by the A's from the above example.

Since there is no way to unhook the events dynamically. I think I am trying to use events in the wrong place.

Thanks

Tom





Re: Visual C# General Events and Handlers

TomPearson

My post was really trying to answer a couple of questions.

1. Does an object reference count include the function pointers that a delegate holds (i.e. do I need to remove them ) which from the above would be yes.

2. If i were to remove the handlers from the delegate mid event would they still get called from another post in the c# general section the answer is yes (My posts didn't seem to appear.....so I posted twice)

My aim is to ripple change though a graph of objects, however I think I am using events where I shouldn't be. At best I would be able to build a list of objects to process post event, and even to allow that - due to the fact the data is representing a graph - I would need to store an event state (i.e. has this object already been processed) to avoid an infinite loop which starts to sound overly and unecessarily complex.





Re: Visual C# General Events and Handlers

decyclone

Hi Tom,

In A2 and A3's event handlers, check if they are removed from the graph or not. If they exist in the graph, continue, otherwise exit the function. This way, the event will be raised but not handled by the nodes that are removed from the graph.






Re: Visual C# General Events and Handlers

Rob Teixeira

1. What I mean is that there is no such thing as a "reference count" in the CLR objects. An object is either reachable or not (because no active references point to it, for example). Unreachable objects just sit in memory until the garbage collector wipes them out.

2. It depends on how the multicast delegate is constructed, but the larger issue, in my opinion, is that you cannot guarantee the order the handlers get called.

But yes, sounds like what you really need is a state machine in this case.





Re: Visual C# General Events and Handlers

TomPearson

I like the simplicity and it would work if I hadn't thought of some further issues i.e. that due to the nature of the graph I may get circular references that would result in a continuous loop. The idea was that an event would possibly trigger further events which objects would then react to and this would be my downfall without some complex checks since an event could quite leaglly be triggered in an object multiple times but requiring different results. Although it could still be made to work the hope was the code would be neat and elegant by using events, which isn't now looking likely.

As such I am going to look at an alternative implementation.

Thanks for the responses.

Tom





Re: Visual C# General Events and Handlers

TomPearson

Thanks for the information.