15

Does this code create a memory leak?

WebClient client = new WebClient();

client.DownloadDataCompleted += (sen, args) => {

};
client.DownloadData("http://foo.bar");

As there is no way to actually unsubscribe from the event. Can I say we must never use lambda for event subscription?

Jaggu
  • 6,298
  • 16
  • 58
  • 96

2 Answers2

11

It doesn't create a memory leak so long as you don't hold onto the WebClient itself - when that's eligible for garbage collection, the event handler target can be collected too. You typically wouldn't keep a WebClient around for a long time - they're typically used as one-shot objects.

Additionally, that lambda expression isn't using any variables from this, so it would probably be implemented by a static method with no target anyway... I assume the real situation you're concerned with has a more interesting lambda body.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • But in normal scenarios, if you don't unsubscribe from the event it creates memory leak. I mean I have seen my event handlers firing N number of times previously without unsubscribing. May be this is lambda so it creates a new anonymous class altogether and so we don't see memory leak. Correct me if I am wrong. – Jaggu Sep 08 '11 at 09:53
  • @Jaggu: You'd need to give a lot more detail about what you mean by "in normal scenarios, if you don't unsubscribe from the event it creates a memory leak". I may agree with you in a few specific examples, but not in general. In the case you've given, there wouldn't be another class - there'd just be a static method as you don't capture *any* variables. – Jon Skeet Sep 08 '11 at 09:54
  • Unless you keep hold of a reference to the lambda, the only way to clean the invocation list of an event is if the event publisher (the webclient in this case) clears the event. If you do not unsubscribe the handler, any objects captured by the lambda will NOT be garbage collected until the even publisher (again, the WebClient) is collected. – Gusdor Feb 21 '13 at 15:51
  • @Gusdor: sure - but my point is that usually (in my experience) if you want a different set of handlers, you're more likely to create a new `WebClient` and let the old one get garbage collected... – Jon Skeet Feb 21 '13 at 15:53
  • The question is about how to unsubscribe events, not correct use of webclient. Perhaps it's presence complicates the issue. The second paragraph in your answer is exactly what is required! – Gusdor Feb 21 '13 at 16:08
  • @Gusdor: No, it's *not* about how to unsubscribe events - it's about whether *subscribing* creates a memory leak... and the answer is that it doesn't do so in itself, but it *does* prevent you from unsubscribing. That's fine, so long as you don't require the target of the event handler to be garbage collected before the `WebClient` is. – Jon Skeet Feb 21 '13 at 16:10
3

If you need to unsubscribe from an event, you need an instanced reference. Unfortunately, that means you can't use that particular syntax.

You'd need to remember the delegate instance you used, like that:

var handler = (s, e) => {};

client.DownloadDataCompleted += handler;
...
client.DownloadDataCompleted -= handler;
Evgeny Gavrin
  • 7,627
  • 1
  • 22
  • 27