我正在与之交谈的人提出了一段代码:
private void DownloadInformation(string id)
{
using (WebClient wc = new WebClient())
{
wc.DownloadStringCompleted +=
new DownloadStringCompletedEventHandler(DownloadStringCompleted);
wc.DownloadStringAsync(new Uri("http://www.fake.com/" + id));
}
}
上面是这个的简化版本:
(我已获得作者的许可发布图片。)
让我困扰的是该代码附加了一个事件处理程序,调用了 DownloadStringAsync()
,然后 using
block 结束,调用了 Dispose( )
在 WebClient
上。有什么可以阻止 WebClient
被 using
处理掉,甚至在 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/