【问题标题】:Will an object be disposed automatically after an asynchronous event it subscribed to is raised?对象订阅的异步事件引发后会自动释放吗?
【发布时间】:2011-08-29 02:48:31
【问题描述】:

假设我有一个可以从主线程调用多次的函数。每次调用它时,我都会创建一个WebClient 对象来异步下载一些数据。

我的问题...这样做安全吗? WebClient 对象是否在事件调用后释放?如果不会自动释放内存,我不想继续分配内存。

我的应用程序适用于带有 Silverlight 的 WP7。

谢谢!

void DownloadData(string cURL)
{
    WebClient webClient = new WebClient();
    webClient.DownloadStringCompleted +=
       new System.Net.DownloadStringCompletedEventHandler(
            webClient_DownloadStringCompleted);
    webClient.DownloadStringAsync(new Uri(cURL));
}

static void webClient_DownloadStringCompleted(object sender,
                      System.Net.DownloadStringCompletedEventArgs e)
{
    ...
}

【问题讨论】:

  • 尚不清楚是否有任何活动对象持有对您的 WebClient 对象的引用。 DownloadStringAsync 可能正在设置一些东西来做到这一点,但我更担心它会过早而不是太晚收集垃圾! :)

标签: c# silverlight windows-phone-7 asynchronous webclient


【解决方案1】:

您可以将它放在 using 块中,而不是手动处理 WebClient。

using (WebClient webClient = new WebClient())
{
    // Your business in here...
}

【讨论】:

  • 如果您在此块内的 webclient 上调用异步方法,是否会导致强制它过早处理的问题?
  • 在这种情况下“使用”会做什么?
  • @WessamElMahdy using 语句将在 usingstackoverflow.com/questions/75401/uses-of-using-in-c-sharp 结束时自动处理 webClient 对象
【解决方案2】:

SilverLight version of WebClient 没有实现 IDisposable。你做对了 - webClient 将在时机成熟时自动被垃圾回收。

【讨论】:

  • 今天刚刚在 WP7 应用程序上遇到了这个问题。非常真实。
  • 为什么要实现 iDisposable 呢?
【解决方案3】:

我看到了 2 个问题。首先,webclient 并不是在所有可能的情况下都被释放,其次,WebClient 的引用将被维护,因为您永远不会取消订阅该事件。

我认为这接近它(虽然仍然不完美,想想 ThreadAborted):

void DownloadData(string cURL) 
        {
            WebClient webClient = new WebClient();

            try
            {
                webClient.DownloadStringCompleted += new System.Net.DownloadStringCompletedEventHandler(webClient_DownloadStringCompleted);
                webClient.DownloadStringAsync(new Uri(cURL));
            }
            catch
            {
                webClient.Dispose();
                throw;
            }
        }

        static void webClient_DownloadStringCompleted(object sender, System.Net.DownloadStringCompletedEventArgs e)
        {
            WebClient webClient = (WebClient)sender;

            webClient.DownloadStringCompleted -= webClient_DownloadStringCompleted;

            try
            {

            }
            finally
            {
                webClient.Dispose();
            }
        }

【讨论】:

  • 对不起,我应该提到它。我正在为 WP7 使用 Silverlight,所以 Dispose() 方法不可用。
  • 当一个事件被订阅时,它不是被观察到的(WebClient)保留了对观察者(webClient_DownloadStringCompleted)的引用吗?如果是这样,则无需取消订阅该事件。
  • @Moonlit:很公平,那么我们可以通过完全不关心 dispose 来简化代码
【解决方案4】:

WebClient 没有实现 iDisposable 接口,因此无需进行任何特殊操作即可进行正确的垃圾收集。当 CLR 检测到当前没有对该对象的引用时,它将被安排进行垃圾回收。当然你不知道什么时候会发生,所以内存可能会也可能不会(很可能不会)立即释放。

【讨论】:

  • 其实它确实实现了 Dispose 因为它继承自 Component (msdn.microsoft.com/en-us/library/…)
  • 我撤回我的声明。你其实是对的。对于我可能造成的任何混乱,向任何人道歉。
  • 对不起,我没有提到它。我在 WP7 上使用 Silverlight,所以 Dispose 方法确实没有实现。
  • 即使 WebClient 确实从 Component 继承了一个 Dispose 方法,它显式地而不是隐式地这样做的事实是一个线索,可能不需要在此对象上调用 Dispose。我认为这实际上是正确的答案。
  • @Jeffrey:我总是喜欢同时考虑做出假设是危险的想法和做出例外应该是例外的想法。如果有一个 dispose 方法,则转换为,然后调用它。此外,谁说它的基类实际上实现了 Dispose 不必被释放?
猜你喜欢
  • 2011-09-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-28
  • 2020-07-24
  • 2019-02-11
相关资源
最近更新 更多