If I have a code that looks something like this:
public void Foo()
{
Bar bar = new Bar();
bar.SomeEvent += (sender, e) =>
{
//Do something here
};
bar.DoSomeOtherThingAndRaiseSomeEvent();
}
Will bar be collected when the method runs out of the scope, or will I have to manually unsubscribe from the event to prevent a memory leak because of a reference to SomeEvent?
Your situation is fine; the event subscriber will not prevent the publisher from being collected, but the opposite can happen.
For example,
class Foo
{
public event EventHandler FooEvent;
void LeakMemory()
{
Bar bar = new Bar();
bar.AttachEvent(this);
}
}
class Bar
{
void AttachEvent(Foo foo)
{
foo.FooEvent += (sender, e) => { };
}
}
In this case, the instance of Bar created within LeakMemory can't be collected until either
The anonymous method represented by the lambda is removed from FooEvent's invocation list
The instance of Foo to which it's attached can be collected
This is because the event (which is just some syntactic sugar over an ordinary delegate instance) holds onto a list of delegates to invoke when it's invoked, and each of these delegates has, in turn, a reference to the object that it's attached to (in this case, the instance of Bar).
Note that we're only talking about collection eligibility here. Just because it's eligible doesn't say anything about when (or even, really, if) it will be collected, just that it can be.
Well, the object bar refers won't be automatically garbage collected immediately... it's just that the bar variable won't prevent it from being garbage collected.
The event handler won't prevent the instance of Bar from being garbage collected either though - the "normal" problem is that an event handler keeps the subscriber of an event from being garbage collected (if it uses an instance method or captures "this" in an anonymous function). It doesn't usually affect the publisher being garbage collected. Just remember that the publisher needs to keep a reference to all the subscribers - the subscriber doesn't need to remember what it's subscribed to, unless it explicitly wants to unsubscribe or use some other member later.
Assuming nothing else is keeping your instance of Bar alive, your code should be fine.
The above answers are correct; I just wanted to make a note. Anonymous delegates used as handlers can only be unsubscribed if you retain some other reference to the delegate/lambda. This is because lambdas are "function literals", kind of like string literals, however unlike strings they are NOT compared semantically when determining equality:
public event EventHandler MyEvent;
...
//adds a reference to this named method in the context of the current instance
MyEvent += Foo;
//Adds a reference to this anonymous function literal to MyEvent
MyEvent += (s,e) => Bar();
...
//The named method of the current instance will be the same reference
//as the named method.
MyEvent -= Foo;
//HOWEVER, even though this lambda is semantically equal to the anonymous handler,
//it is a different function literal and therefore a different reference,
//which will not match the anonymous handler.
MyEvent -= (s,e) => Bar();
var hasNoHandlers = MyEvent == null; //false
//To successfully unsubscribe a lambda, you have to keep a reference handy:
EventHandler myHandler = (s,e) => Bar();
MyEvent += myHandler;
...
//the variable holds the same reference we added to the event earlier,
//so THIS call will remove the handler.
MyEvent -= myHandler;
Related
Preface: I know how to solve the problem. I want to know why it arises. Please read the question from top to bottom.
As we all (should) know, adding event handlers can cause memory leaks in C#. See Why and How to avoid Event Handler memory leaks?
On the other hand, objects often have similar or connected life cycles and deregistering event handlers is not necessary. Consider this example:
using System;
public class A
{
private readonly B b;
public A(B b)
{
this.b = b;
b.BEvent += b_BEvent;
}
private void b_BEvent(object sender, EventArgs e)
{
// NoOp
}
public event EventHandler AEvent;
}
public class B
{
private readonly A a;
public B()
{
a = new A(this);
a.AEvent += a_AEvent;
}
private void a_AEvent(object sender, EventArgs e)
{
// NoOp
}
public event EventHandler BEvent;
}
internal class Program
{
private static void Main(string[] args)
{
B b = new B();
WeakReference weakReference = new WeakReference(b);
b = null;
GC.Collect();
GC.WaitForPendingFinalizers();
bool stillAlive = weakReference.IsAlive; // == false
}
}
A and B reference each other implicitly via events, yet the GC can delete them (because it's not using reference counting, but mark-and-sweep).
But now consider this similar example:
using System;
using System.Timers;
public class C
{
private readonly Timer timer;
public C()
{
timer = new Timer(1000);
timer.Elapsed += timer_Elapsed;
timer.Start(); // (*)
}
private void timer_Elapsed(object sender, ElapsedEventArgs e)
{
// NoOp
}
}
internal class Program
{
private static void Main(string[] args)
{
C c = new C();
WeakReference weakReference = new WeakReference(c);
c = null;
GC.Collect();
GC.WaitForPendingFinalizers();
bool stillAlive = weakReference.IsAlive; // == true !
}
}
Why can the GC not delete the C object? Why does the Timer keep the object alive? Is the timer kept alive by some "hidden" reference of the timer mechanics (e.g. a static reference)?
(*) NB: If the timer is only created, not started, the issue does not occur. If it's started and later stopped, but the event handler is not deregistered, the issue persists.
The timer logic relies on an OS functionality. It is actually the OS that fires the event. OS in turn uses CPU interrupts to implement that.
The OS API, aka Win32, does not hold references to any objects of any kind. It holds memory addresses of functions which it has to call when a timer event happens. .NET GC has no way to track such "references". As a result a timer object could be collected without unsubscribing from the low-level event. It is a problem because OS would try to call it anyway and would crash with some weird memory access exception. That's why .NET Framework holds all such timer objects in the statically referenced object and removes them from that collection only when you unsubscribe.
If you look at the root of your object using SOS.dll you will get the next picture:
!GCRoot 022d23fc
HandleTable:
001813fc (pinned handle)
-> 032d1010 System.Object[]
-> 022d2528 System.Threading.TimerQueue
-> 022d249c System.Threading.TimerQueueTimer
-> 022d2440 System.Threading.TimerCallback
-> 022d2408 System.Timers.Timer
-> 022d2460 System.Timers.ElapsedEventHandler
-> 022d23fc TimerTest.C
Then if you look at the System.Threading.TimerQueue class in something like dotPeek, you will see that it is implemented as a singleton and it holds a collection of timers.
That's how it works. Unfortunately the MSDN documentation is not crystal clear about it. They just assumed that if it implements IDisposable then you should dispose it no question asked.
Is the timer kept alive by some "hidden" reference of the timer mechanics (e.g. a static reference)?
Yes. It is built in the CLR, you can see a trace of it when you use the Reference Source or a decompiler, the private "cookie" field in the Timer class. It is passed as the second argument to the System.Threading.Timer constructor that actually implements the timer, the "state" object.
The CLR keeps a list of enabled system timers and adds a reference to the state object to ensure it doesn't get garbage collected. Which in turn ensures that the Timer object doesn't get garbage collected as long as it is in the list.
So getting a System.Timers.Timer garbage collected requires that you call its Stop() method or set its Enabled property to false, same thing. Which cause the CLR to remove the system timer from the list of active timers. Which also removes the reference to the state object. Which then makes the timer object eligible for collection.
Clearly this is desirable behavior, you do not typically want to have a timer just disappear and stop ticking while it is active. Which will happen when you use a System.Threading.Timer, it stops calling its callback if you don't keep a reference to it, either explicitly or by using the state object.
I think this is related to the way that the Timer is implemented. When you call Timer.Start(), it sets Timer.Enabled = true. Look at the implementation of Timer.Enabled:
public bool Enabled
{
[TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
get
{
return this.enabled;
}
set
{
if (base.DesignMode)
{
this.delayedEnable = value;
this.enabled = value;
}
else if (this.initializing)
{
this.delayedEnable = value;
}
else if (this.enabled != value)
{
if (!value)
{
if (this.timer != null)
{
this.cookie = null;
this.timer.Dispose();
this.timer = null;
}
this.enabled = value;
}
else
{
this.enabled = value;
if (this.timer == null)
{
if (this.disposed)
{
throw new ObjectDisposedException(base.GetType().Name);
}
int dueTime = (int) Math.Ceiling(this.interval);
this.cookie = new object();
this.timer = new Timer(this.callback, this.cookie, dueTime, this.autoReset ? dueTime : 0xffffffff);
}
else
{
this.UpdateTimer();
}
}
}
}
}
It looks like a new timer is created, with a cookie object passed to it (very odd!). Following that call path leads to some other complex code involving creating a TimerHolder and a TimerQueueTimer. I expect at some point a reference held outside the Timer itself is created, until such time as you call Timer.Stop() or Timer.Enabled = false.
This isn't a definitive answer, since none of the code I posted creates such a reference; but it's complicated enough down in the guts to lead me to suspect that something like that is happening.
If you have Reflector (or similar) have a look and you'll see what I mean. :)
Because Timer is still active. (Event handler is not removed for Timer.Elapsed).
If you want to properly dispose, Implement IDisposable interface, remove the event handler in the Dispose method, and use the using block or call the Dispose manually. The issue will not occur.
Example
public class C : IDisposable
{
...
void Dispose()
{
timer.Elapsed -= timer_elapsed;
}
}
And then
C c = new C();
WeakReference weakReference = new WeakReference(c);
c.Dispose();
c = null;
I think the problem arises from this line;
c = null;
In general, most developers think that making an object equal to null results in object to be deleted by garbage collector. But this is not the case; in fact only a reference to a memory location (where c object is created) is deleted; if there are any other references to the related memory location, object will not be marked for deletion. In this case, since Timer is referencing the related memory location, object will not be deleted by garbage collector.
Let's first talk about Threading.Timer. Internally, the timer will construct a TimerQueueTimer object using callback and state passed to Timer ctor (say new Threading.Timer(callback, state, xxx, xxx). The TimerQueueTimer will be added to a static list.
If callback method and state have no "this" info (say using static method for callback and null for state), then the Timer object can be GCed when no reference.
On the other hand, if a member method is used for callback, the delegate containing "this" will be stored in the static list mentioned above. So Timer object cannot be GCed since the "C" (in your example) object is still referenced.
Now let's back to System.Timers.Timer which internally wraps Threading.Timer. Note that when the former constructs the latter, a System.Timers.Timer member method is used, so System.Timers.Timer object cannot be GCed.
(I know the title sounds easy, but hold on—this probably isn't the question you think it is.)
In VB.NET I was able to write custom events. For an example, I had a separate thread that would periodically raise an event and on that event the GUI would need to be updated. I didn't want the busy thread to bother with UI calculations and I didn't want to put Me.Invoke(Sub() ...) in the event handler since it was also called from the GUI thread.
I came up with this very useful bit of code. The GUI thread would set EventSyncInvoke = Me (the main form). The thread could then simply raise the event TestEvent as usual, no special code, and it would be seamlessly executed on the GUI thread:
Private TestEventDelegate As EventHandler
Public EventSyncInvoke As System.ComponentModel.ISynchronizeInvoke
Public Custom Event TestEvent As EventHandler
AddHandler(value As EventHandler)
TestEventDelegate = [Delegate].Combine(TestEventDelegate, value)
End AddHandler
RemoveHandler(value As EventHandler)
TestEventDelegate = [Delegate].Remove(TestEventDelegate, value)
End RemoveHandler
RaiseEvent(sender As Object, e As System.EventArgs)
If EventSyncInvoke IsNot Nothing Then
EventSyncInvoke.Invoke(TestEventDelegate, {sender, e})
Else
TestEventDelegate.Invoke({sender, e})
End If
End RaiseEvent
End Event
Now in C# I can do this much:
public event EventHandler TestEvent
add
{
testEventDelegate = (EventHandler)Delegate.Combine(testEventDelegate, value);
}
remove
{
testEventDelegate = (EventHandler)Delegate.Remove(testEventDelegate, value);
}
}
But where is the ability to do custom raising?
The other answers told me the fact that I couldn't do this directly in C#, but not the rationale behind why I can't and why I wouldn't want to. It took me a while to understand how C# events worked in comparison to VB.NET. So this explanation is for others who don't have a good grasp on this to start thinking along the right lines.
Honestly, I was so used to the boilerplate OnTestEvent format that I didn't quite like the idea of making it different from the rest of the helper methods. :-) But now that I understand the rationale, I see that it is actually the best place to put this stuff.
VB.NET allows you to hide the background details of calling the delegates with the RaiseEvent keyword. RaiseEvent calls either the event delegate or your custom RaiseEvent section for a custom event.
In C#, there is no RaiseEvent. Raising an event is basically no more than calling a delegate. No custom RaiseEvent sections can be seamlessly called when all you're doing to raise it is calling a delegate. So for C#, custom events are like skeletons, implementing add and remove for events but not implementing the ability to raise them. It's like having to replace all your RaiseEvent TestEvent(sender, e) with the code from the custom RaiseEvent section.
For a normal event, raising looks roughly like NormalEvent(sender, e). But as soon as you put in a custom add and remove, you must use whatever variable you used in the add and remove because the compiler isn't doing it anymore. It's like automatic properties in VB.NET: once you put in a getter and setter manually, you have to declare and handle your own local variable. So instead of TestEvent(sender, e), use testEventDelegate(sender, e). That's where you rerouted the event delegates.
I compared moving from VB.NET to C# with having to replace each of your RaiseEvents with your custom RaiseEvent code. A RaiseEvent code section is basically an event and a helper function rolled together. It's actually standard to only have one instance of a RaiseEvent in either VB.NET or C# inside a protected OnTestEvent method and call that method to raise the event. This allows any code with access to the protected (or private or public) OnTestEvent to raise the event. For what you want to do, just putting it in the method is easier, simpler and performs slightly better. This is best practice.
Now if you really want to want (or need) somehow to mimic VB.NET's RaiseEvent nitty-gritty-hiding call SomeDelegate(sender, e) and have the magic happen, you can simply hide the nitty-gritty inside a second delegate:
NiceTestEvent = (sender, e) => eventSyncInvoke.Invoke(testEventDelegate, new object[] { sender, e });
Now you can call NiceTestEvent(sender, e). You won't be able to call TestEvent(sender, e) though. TestEvent is only for outside code to add and remove through, as Visual Studio will tell you.
In C#, there isn't any RaiseEvent block. You would do the same thing by creating a method for raising your event.
Here is a working example. In the C# version, you do not even need to use the add and remove block -- you can use the default implementation for that and just create a custom raise method that raises your event.
Below is a working program (the form is just a Windows Forms form with a single button on it).
// Here is your event-raising class
using System;
using System.ComponentModel;
namespace ClassLibrary1
{
public class Class1
{
public ISynchronizeInvoke EventSyncInvoke { get; set; }
public event EventHandler TestEvent;
private void RaiseTestEvent(EventArgs e)
{
// Take a local copy -- this is for thread safety. If an unsubscribe on another thread
// causes TestEvent to become null, this will protect you from a null reference exception.
// (The event will be raised to all subscribers as of the point in time that this line executes.)
EventHandler testEvent = this.TestEvent;
// Check for no subscribers
if (testEvent == null)
return;
if (EventSyncInvoke == null)
testEvent(this, e);
else
EventSyncInvoke.Invoke(testEvent, new object[] {this, e});
}
public void Test()
{
RaiseTestEvent(EventArgs.Empty);
}
}
}
// Here is a form that tests it -- if you run it, you will see that the event is marshalled back to
// the main thread, as desired.
using System;
using System.Threading;
using System.Windows.Forms;
namespace ClassLibrary1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
this.TestClass = new Class1();
this.TestClass.EventSyncInvoke = this;
this.TestClass.TestEvent += new EventHandler(TestClass_TestEvent);
Thread.CurrentThread.Name = "Main";
}
void TestClass_TestEvent(object sender, EventArgs e)
{
MessageBox.Show(this, string.Format("Event. Thread: {0} Id: {1}", Thread.CurrentThread.Name, Thread.CurrentThread.ManagedThreadId));
}
private Class1 TestClass;
private void button1_Click(object sender, EventArgs e)
{
// You can test with an "old fashioned" thread, or the TPL.
var t = new Thread(() => this.TestClass.Test());
t.Start();
//Task.Factory.StartNew(() => this.TestClass.Test());
}
}
}
You simply can't. But since events can be raised only from inside the type that declares them, you can create a helper method that executes your specific raising code. And then just make sure you don't raise the event directly outside that method.
AFAIK custom event raising as in VB.NET does not exist in C#. However, you could wrap the actual event handler delegates (passed to add as value) in a lambda and subscribe that lambda to the event instead of the original delegate:
add
{
testEventDelegate = Delegate.Combine(testEventDelegate, (s, e) => { ... } )
}
(Above code untested, syntax might be slightly off. I'll fix it as soon as I can test it.)
Crude, but working example:
The following is a concrete example of the above. I am not convinced myself that the following is good, solid code, nor that it would work in all circumstances (such as multi-threading etc.)... nevertheless, here it is:
class Foo
{
public Foo(SynchronizationContext context)
{
this.context = context ?? new SynchronizationContext();
this.someEventHandlers = new Dictionary<EventHandler, EventHandler>();
}
private readonly SynchronizationContext context;
// ^ could also use ISynchronizeInvoke; I chose SynchronizationContext
// for this example because it is independent from, but compatible with,
// Windows Forms.
public event EventHandler SomeEvent
{
add
{
EventHandler wrappedHandler =
(object s, EventArgs e) =>
{
context.Send(delegate { value(s, e); }, null);
// ^ here is where you'd call ISynchronizeInvoke.Invoke().
};
someEvent += wrappedHandler;
someEventHandlers[value] = wrappedHandler;
}
remove
{
if (someEventHandlers.ContainsKey(value))
{
someEvent -= someEventHandlers[value];
someEventHandlers.Remove(value);
}
}
}
private EventHandler someEvent = delegate {};
private Dictionary<EventHandler, EventHandler> someEventHandlers;
public void RaiseSomeEvent()
{
someEvent(this, EventArgs.Empty);
// if this is actually the only place where you'd invoke the event,
// then you'd have far less overhead if you moved the ISynchronize-
// Invoke.Invoke() here and forgot about all the wrapping above...!
}
}
(Note that I've used the C# 2 anonymous delegate {} syntax for brevity.)
Can you see downsides to this one-liner other than the fact that multiple uses of it would violate the DRY principle? It seems straightforward but the fact that I haven't seen others propose it makes me wonder if there's a downside to it.
This bit of code creates a WeakReference to a method and then registers an event handler that invokes the reference's target.
SomeEvent += (sender, e) => ((Action)(new WeakReference((Action)ProcessEvent)).Target)();
Thanks,
Ben
I don't think that pattern does what you expect. Are you trying to prevent the event from holding a reference to the current object so as to prevent memory leaks? The lambda expression will capture the value of this in order to evaluate ProcessEvent (assuming ProcessEvent is an instance method), so you will still have the leak. This code is the same as doing SomeEvent += (sender, e) => ProcessEvent();.
You may be trying to do something more like this (which also isn't what you want):
var reference = new WeakReference((Action)ProcessEvent);
SomeEvent += (sender, e) => ((Action)reference.Target)();
Now the lambda expression will capture the WeakReference, so you won't have a strong reference to this. Unfortunately, nothing else is referencing the delegate created from ProcessEvent, so it will be removed on the next GC even if this is still alive. (This also doesn't check for Target being null).
You could try something like this:
public EventHandler MakeWeakHandler(Action action, Action<EventHandler> remove)
{
var reference = new WeakReference(action.Target);
var method = action.Method;
EventHandler handler = null;
handler = delegate(object sender, EventArgs e)
{
var target = reference.Target;
if (target != null)
{
method.Invoke(target, null);
}
else
{
remove(handler);
}
};
return handler;
}
and then use it like this:
SomeEvent += MakeWeakHandler(ProcessEvent, h => SomeEvent -= h);
That will keep a weak reference to the receiver of ProcessEvent, and will automatically remove the event handler from the event after it has been collected, which should prevent memory leaks as long as the event is raised regularly.
Its not very readable. And if you have to debug it by stepping through, any one of those actions could fail, but that single line would fail. Also, you'd only get that single line referenced in a stack trace.
You generally want to avoid doing too many things in a single line for maintainability.
I have some code in my project that saves an object to the database, once this is done I want it to call a series of other methods.
I was thinking about allowing other methods to subscribe to this event so I can add more as I need to. The idea I had for this was to create an array of Delegates allowing other methods to register, then when the object had been saved it could loop through the delegates and call each one.
Would this be bad practise or is there a better way of doing this?
Thanks
Event delegates are multicast, which means that they can hold references to more than one event handling method - see the MSDN documentation for Delegate and MulticastDelegate.
The syntax for subscribing to an event gives a clue:
MyEvent += MyHandler; // subscribe to an event
MyEvent -= MyHandler; // unsubscribe from an event
You can subscribe as many delegates as you want to a single event. Under the hood .Net keeps these as an ordered collection anyway.
The standard pattern for this is:
//in your class
public EventHandler<MyEvtArgs> MyEvent;
protected void OnMyEvent ( MyEvtArgs args ) {
if(MyEvent != null) //make sure there is at least 1 subscriber
MyEvent(this, args);
}
Then to call this:
var myInstance = new MyClass();
// all of these can convert to EventHandler<MyEvtArgs> (object, MyEvtArgs)
myInstance.MyEvent += (sender, e) => { /* do something 1 */ };
myInstance.MyEvent += (sender, e) => { /* do something 2 */ };
myInstance.MyEvent += localMethod;
Now when your protected OnMyEvent method is called inside your class all of these events will fire - in order.
You can also remove items from this collection:
myInstance.MyEvent -= localMethod;
You don't need an array. Just let anyone subscribe to one.
You can use a normal event for this. The runtime will handle looping over all fields.
public event EventHandler<EventArgs> WritingToDatabaseFinished;
protected void OnWritingToDatabaseFinished(EventArgs args)
{
EventHandler<EvetnArgs> handler = WritingToDatabaseFinished;
if (handler != null)
{
handler(this, args);
}
}
Your code calls
OnWritingToDatabaseFinished(args);
All methods that want to be informed have to register to the event:
WritingToDatabaseFinished += new EventHandler<EventArgs>(handlermethod);
Every handler that has been registered in the above way will be called when you call OnWritingToDatabaseFinished.
All you need is a multicast delegate. You don't need an array at all. You use += to add a reference to the delegate, and a -= to remove the reference.
I would recommend that you look at using a weak event handler instead. Take a look at this link to see why you'd use a weak event instead of a weak delegate.
Delegates are already multicast, so no need for a delegate array. Now, the recommended way of adding event support to your class is:
Add a public delegate (this will be your event handler)
public delegate void DatabaseEventHandler(object sender, DatabaseEventArgs e);
Add a public event, of your delegate type.
public event DatabaseEventHandler DatabaseDone;
Now, the event should send 2 parameters. The sender (this, usually), and the EventArgs. You should create a new class from System.EventArgs, and send the appropriate information within that class.
I have the following code:
public List<IWFResourceInstance> FindStepsByType(IWFResource res)
{
List<IWFResourceInstance> retval = new List<IWFResourceInstance>();
this.FoundStep += delegate(object sender, WalkerStepEventArgs e)
{
if (e.Step.ResourceType == res) retval.Add(e.Step);
};
this.Start();
return retval;
}
Notice how I register my event member (FoundStep) to local in-place anonymous function.
My question is: when the function 'FindStepByType' will end - will the anonymous function be removed automatically from the delegate list of the event or I have to manually remove it before steping out the function? (and how do I do that?)
I hope my question was clear.
Your code has a few problems (some you and others have identified):
The anonymous delegate cannot be removed from the event as coded.
The anonymous delegate will live longer than the life of the method calling it because you've added it to FoundStep which is a member of this.
Every entry into FindStepsByType adds another anonymous delegate to FoundStep.
The anonymous delegate is a closure and effectively extends the lifetime of retval, so even if you stop referencing retval elsewhere in your code, it's still held by the anonymous delegate.
To fix this, and still use an anonymous delegate, assign it to a local variable, and then remove the handler inside a finally block (necessary in case the handler throws an exception):
public List<IWFResourceInstance> FindStepsByType(IWFResource res)
{
List<IWFResourceInstance> retval = new List<IWFResourceInstance>();
EventHandler<WalkerStepEventArgs> handler = (sender, e) =>
{
if (e.Step.ResourceType == res) retval.Add(e.Step);
};
this.FoundStep += handler;
try
{
this.Start();
}
finally
{
this.FoundStep -= handler;
}
return retval;
}
With C# 7.0+ you can replace the anonymous delegate with a local function, achieving the same effect:
public List<IWFResourceInstance> FindStepsByType(IWFResource res)
{
var retval = new List<IWFResourceInstance>();
void Handler(object sender, WalkerStepEventArgs e)
{
if (e.Step.ResourceType == res) retval.Add(e.Step);
}
FoundStep += Handler;
try
{
this.Start();
}
finally
{
FoundStep -= Handler;
}
return retval;
}
Below is approach about how unsubscribe event in anonymous method:
DispatcherTimer _timer = new DispatcherTimer();
_timer.Interval = TimeSpan.FromMilliseconds(1000);
EventHandler handler = null;
int i = 0;
_timer.Tick += handler = new EventHandler(delegate(object s, EventArgs ev)
{
i++;
if(i==10)
_timer.Tick -= handler;
});
_timer.Start();
No, it will not be removed automatically. In this sense, there's not a difference between an anonymous method and a "normal" method. If you want, you should manually unsubscribe from the event.
Actually, it'll capture other variables (e.g. res in your example) and keep them alive (prevents garbage collector from collecting them) too.
When using an anonymous delegate (or a lambda expression) to subscribe to an event does not allow you to easily unsubscribe from that event later. An event handler is never automatically unsubscribed.
If you look at your code, even though you declare and subscribe to the event in a function, the event you are subscribing to is on the class, so once subscribed it will always be subscribed even after the function exits. The other important thing to realize is that each time this function is called, it will subscribe to the event again. This is perfectly legal since events are essentially multicast delegates and allow multiple subscribers. (This may or may not be what you intend.)
In order to unsubscribe from the delegate before you exit the function, you would need to store the anonymous delegate in a delegate variable and add the delegate to the event. You should then be able to remove the delegate from the event before the function exits.
For these reasons, if you will have to unsubscribe from the event at some later point it is not recommended to use anonymous delegates. See How to: Subscribe to and Unsubscribe from Events (C# Programming Guide) (specifically the section titled "To subscribe to events by using an anonymous method").