2010-03-24 90 views
3

我正在使用Silverlight/WCF应用程序,当然在整个Silverlight程序中都有很多异步调用。我想知道如何处理创建客户端类和订阅的最佳方式。具体来说,如果我在一个方法中订阅一个事件,它返回后是否超出范围?C#异步调用垃圾回收

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? 
    } 
} 

如果我再次调用函数并创建另一个订阅,会遇到问题吗?

在此先感谢任何回复的人。

+0

关于GC拧你,你没事按照http://stackoverflow.com/questions/421547/does-the-garbage-collector-destroy-temporarily-unreferenced-objects-during-async – Tanzelax 2010-03-24 18:05:51

回答

2

你不会遇到问题。它会生成一个新的WcfClient实例,两者都将在完成时调用您的OnMethodCompleted回调。

+0

什么词“都”是指? – 2010-03-24 17:56:54

+0

@Daniel,“如果我再次调用函数并创建另一个订阅” – Tanzelax 2010-03-24 17:59:54

+0

啊,gotcha ..... – 2010-03-24 18:01:29

3

您不应该让WCF客户端代理简单地超出这个范围。你的代码可以工作,但也会泄漏资源。 WCF客户端全部实现IDisposable,但这是一种情况,您不能只使用usingDispose; Service Proxy Helper可用于同步操作,但其中的清理代码演示了如何在任何情况下安全地处理客户端。

在制作异步这样的操作时,需要以类似的方式管理该客户端的生命周期。通常WCF客户端应该自己实现IDisposable这个WCF客户端的所有类,并在某个私有字段中引用该客户端,并在其处理方法中调用客户端上的Close/Abort

一般来说,无论哪个类实际实现了异步回调方法,都将是所有者,因此该类应该管理生命周期;因此,如果您确实需要“按需”客户端,则在回调完成后执行清理也可能有意义。 WCF客户端创建起来并不便宜,因此您应该尽可能长时间保持它们,而不是像这样临时创建它们;将它们视为应用程序范围的依赖关系。

如果你只是保持客户端实例,那么你也不需要继续订阅它的事件;这个问题就有效地消失了。

+0

+1,因为这看起来是正确的建议,但它会真的长期泄露资源吗?或者它会在某个时候完成? – 2010-03-24 18:20:22

+0

感谢您的回复。我认为批准的方式是在课堂上创建它,这很好地证实了这一点。这似乎是我在订阅和取消订阅用户可能会或可能不会使用的事件时做错了事情。 – Troy 2010-03-24 18:29:35

+0

@Daniel Earwicker:当然,所有东西最终都会被确定下来 - 所以会有'SqlConnection'或'Bitmap' - 问题是*时的问题。如果你坚持不受管理的资源(套接字,互斥锁,句柄等),那么如果你不释放它们,那么你最终可能会饿死系统,因为GC只会在需要*内存*时才会启动。 – Aaronaught 2010-03-24 19:17:08