c# - 事件触发前的对象处理和垃圾收集

标签 c# .net garbage-collection event-handling using-statement

我正在与之交谈的人提出了一段代码:

private void DownloadInformation(string id)
{
    using (WebClient wc = new WebClient())
    {
        wc.DownloadStringCompleted += 
            new DownloadStringCompletedEventHandler(DownloadStringCompleted);
        wc.DownloadStringAsync(new Uri("http://www.fake.com/" + id));
    }
}

上面是这个的简化版本:

enter image description here

(我已获得作者的许可发布图片。)

让我困扰的是该代码附加了一个事件处理程序,调用了 DownloadStringAsync(),然后 using block 结束,调用了 Dispose( )WebClient 上。有什么可以阻止 WebClientusing 处理掉,甚至在 DownloadStringAsync() 完成和 DownloadStringCompleted< 之前收集垃圾 事件触发?

有一个更新的方法,DownloadStringTaskAsync(),我想将其与 await 结合使用:

private async Task DownloadInformation(string id)
{
    using (WebClient wc = new WebClient())
    {
        wc.DownloadStringCompleted += DownloadStringCompleted;
        await wc.DownloadStringTaskAsync(new Uri("http://www.fake.com/" + id));
    }
}

然而,即便如此......我基本上还是敢打赌,事件触发器和处理程序会在 WebClient 被处理掉之前被调用。

在这种情况下,我是否误解了 WebClient 的生命周期,或者这是一个糟糕的代码设计?

最佳答案

WebClient 没有实现 IDisposable,它的基类 Component 实现了。

Component 类处理使用其 Events 属性注册但 WebClient 不使用该属性的任何事件处理程序。

在 WebClient 上调用 Dispose 不会影响 webclient 管理的任何状态。

内部资源的实际处理是在私有(private)方法 DownloadBits 和内部类 DownloadBitsState 中完成的。

因此,由于过早释放资源,您显示的代码到目前为止没有任何影响。然而,这是由实现细节引起的。这些在未来可能会改变。

由于框架会跟踪挂起的回调,您也不必担心过早的垃圾回收,如 this answer 中所述。 , 由 Alexei Levenkov 友情提供。

关于c# - 事件触发前的对象处理和垃圾收集,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39609125/

相关文章:

c# - 如何序列化 IList<T>?

c# - 代码首次尝试创建数据库时出现异常

c# - 正确定位多个框架时如何使用条件符号(VS2017)

java - 了解 GC 失败消息

c# - 限制 C# 应用程序中托管堆的大小

c# - 确保控制台项目中的 app.config 复制到 Web 项目的 bin 文件夹

c# - 从列表中检索项目

c# - .NET 相当于 Java 的 TreeSet.floor 和 TreeSet.ceiling

.net - 如何保护 WCF 客户端应用程序中的敏感数据?

java - 本地字符串文字的内存分配?