C# - Ensuring Events Don't Stack
HI,
I have a button click event where a user de开发者_如何转开发fined type is initialised, and an event is set-up.
This button is used numerous times, and I don't want the events to stack. Therefore I have unsubscribed to the event in the finally block.
The code is similar to below:
try {
bar = new foo();
bar.event += new event(method);
dosomething()
}
finally {
bar.event -= new event(method);
}
It seems to work okay so far, however I'm concerned with the finally block being processed before the doSomething method has completed and thus made use of the event.
Would the method be allowed to process before the finally block is called?
What I usually do is have an inEvent boolean variable that is checked every time an event is triggered. The code will look like this:
bool inEvent = false;
...
private void Button1_Click(object source, EventArgs e)
{
if (inEvent)
return;
try
{
inEvent= true;
dosomething();
}
finally
{
inEvent = false;
}
}
The finally block will execute, when
- dosomething has completed successfully
- dosomething throws an exception
- foo constructor throws an exception
In the last case, it will access the uninitialized variable bar and throw a NullReferenceException. So you better place the bar = new foo();
before the try block.
the finally block by definition can only be exceuted after execution has left the body of the dosomething() method, be if through a the return statement or the normale end of the function or an exception that gets thrown inside this method's body which doesn't get handled in this function.
The finally
block will not run before dosomething
returns or throws.
It's better to unsubscribe in the generated event.
void somewhere()
{
bar = new foo();
bar.event += method;
dosomething()
}
void method(object source, EventArgs e)
{
((bar)source).event -= method;
}
Yes (unless an exception is thrown before that of course). Your idea is sound.
Presumably, logic in DoSomething() raises the event you're interested in? If so, you will have a problem if DoSomething() raises the event asyncronously - if this is the case, it's likely that DoSomething will return, then your finally will run and unsubscribe from the event. When the event eventually fires from code initated in DoSomething, you will miss it.
If there is no asynchronous logic in DoSomething (i.e. if the event is raised synchronously), then your general approach is fine. But you might want to think about getting DoSomething to return a value, rather than raising an event
Events are called synchronously. So unless you are writing any asynchronous code in your DoSomething()
method, the finally will always run after execution has completed (or an exception is thrown).
What you seem to be getting at is that event handler references hanging around will prevent an object from being collected, which can cause memory problems. You have the right idea that in order to completely free and object, you should remove all events after you are done with it.
精彩评论