views:

365

answers:

2

Hello. I am working on a Silverlight/WCF application and of course have numerous async calls throughout the Silverlight program. I was wondering on how is the best way to handle the creation of the client classes and subscribing. Specifically, if I subscribe to an event in a method, after it returns does it fall out of scope?

internal MyClass 
{
    public void OnMyButtonClicked()
    {
        var wcfClient = new WcfClient();
        wcfClient.SomeMethodFinished += OnMethodCompleted;
        wcfClient.SomeMethodAsync();
    }

    private void OnMethodCompleted(object sender, EventArgs args)
    {
        //Do something with the result

        //After this method does the subscription to the event
        //fall out of scope for garbage collection?
    }
}

Will I run into problems if I call the function again and create another subscription?

Thanks in advance to anyone who responds.

+2  A: 

You won't run into problems. It will generate a new WcfClient instance, and both will call your OnMethodCompleted callback on completion.

Reed Copsey
What does the word "both" refer to?
Daniel Earwicker
@Daniel, "if I call the function again and create another subscription"
Tanzelax
Ah, gotcha.....
Daniel Earwicker
+3  A: 

You shouldn't let WCF client proxies simply fall out of scope like this. Your code will work but it will also leak resources. WCF clients all implement IDisposable, but this is one case where you can't just use using or Dispose; the Service Proxy Helper can be used for synchronous operations but the cleanup code in there demonstrates how to safely dispose of the client in any context.

When making async operations like this, something needs to be managing the lifetime of that client in a similar fashion. Normally whatever class "owns" the WCF client should implement IDisposable itself, keep a reference to that client in a private field somewhere, and invoke Close/Abort on the client in its disposal method.

Generally, whichever class actually implements the async callback method is going to be the owner, and so that class should be managing the lifetime; therefore, if you really need an "on-demand" client, it may also make sense to perform the cleanup after the callback is finished.

WCF clients are not cheap to create, either, so you should actually try to keep them around as long as possible and not create them ad-hoc like this; think of them as application-wide dependencies.

If you just keep the client instance around, then you don't need to keep subscribing to its events, either; the question effectively goes away.

Aaronaught
+1, as this seems like the right advice, but will it really leak resources in the long term? Or will it get finalized at some point?
Daniel Earwicker
Thanks for your response. I thought the approved way would be to create it at the class level and this pretty much confirms it. It just seemed like I was doing something wrong subscribing and unsubscribing to events that the user may or may not use.
Troy
@Daniel Earwicker: Everything will eventually get finalized, of course - so will a `SqlConnection` or `Bitmap` - the question is *when*. if you're holding onto unmanaged resources (sockets, mutexes, handles, etc.), you can end up starving the system if you don't release them because the GC will only kick in when it needs *memory*.
Aaronaught
@Troy: The main thing you need to remember about events is that subscribing to an event will keep the *subscriber* alive as long as the *source* is alive, which can sometimes complicate garbage collection. Essentially you just need to make sure you unsubscribe from events where appropriate; if you "own" the thing you're subscribing to, then unsubscribing is generally unnecessary, but if you take a reference to it from the outside world, you do need to unsubscribe when you're done with it.
Aaronaught
@Aaronaught - sorry, I wasn't clear. My question was about whether a WCF client class had finalizer - you seemed to imply it didn't, and I'm interested in examples of classes that implement `IDisposable` but do not have a finalizer. (You're wrong to say *everything* will get finalized; not all objects that are `IDisposable` have a finalizer).
Daniel Earwicker
@Daniel Earwicker: `ClientBase<T>` has a finalizer, and you're right, not all `IDisposable` instances do. That said, any class which wraps unmanaged resources and implements `IDisposable` but doesn't have a finalizer hasn't implemented the pattern correctly; you only generally leave out the finalizer when the class wraps internal `IDisposable` resources only (as opposed to directly working with unmanaged resources). Phew, that was a mouthful.
Aaronaught
Yeah that sounds more like it.
Daniel Earwicker