.NET:异步下载时是否需要保留对 WebClient 的引用?

.NET: Do I need to keep a reference to WebClient while downloading asynchronously?(.NET:异步下载时是否需要保留对 WebClient 的引用?)

本文介绍了.NET:异步下载时是否需要保留对 WebClient 的引用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在一段生产代码中使用如下方法:

I use the following method in a piece of production code:

private void DownloadData(Uri uri)
{
    WebClient webClient = new WebClient();
    DownloadDataCompletedEventHandler eh = null;
    eh = delegate(object sender, DownloadDataCompletedEventArgs e)
        {
            webClient.DownloadDataCompleted -= eh;
            ((IDisposable) webClient).Dispose();
            OnDataDownloaded();
        };
    webClient.DownloadDataCompleted += eh;
    webClient.DownloadDataAsync(uri);
}

我现在担心在调用 DownloadDataCompleted 事件之前被垃圾收集的 WebClient 实例可能会导致难以重现的错误:退出我的 之后DownloadData() 方法,没有明显的对 WebClient 对象的引用,所以这可能会发生.

I am now worried that a hard to reproduce bug might be caused by the WebClient instance being garbage collected before the DownloadDataCompleted event is called: after exiting my DownloadData() method, there are no obvious references to the WebClient object, so that could plausibly happen.

所以我的问题是:这真的会发生吗?我无法重现该问题,因此可能发生了一些内部问题,阻止了 WebClient 对象被垃圾收集(例如,在等待响应时,该对象可能会在某处向全局对象注册自身).

So my question is: can this realistically happen? I can not reproduce the problem, so there might be some internal things happening that prevents the WebClient object from being garbage collected (e.g. the object might register itself with a global object somewhere while waiting for the response).

如果这有什么不同的话,代码在 .NET 2.0 上运行.

The code is running on .NET 2.0 if that makes any difference.

推荐答案

不,在回调完成之前,您的对象不会被 GC-ed.根据 垃圾收集器是否在异步期间销毁临时未引用的对象在 .NET 中调用?,异步 API 保留对您的请求的引用(在异步 IO 操作所在的线程池中),因此在完成之前不会被垃圾收集."

No, your object won't be GC-ed until the callback completes. According to Does the Garbage Collector destroy temporarily unreferenced objects during async calls in .NET?, "the async API keeps a reference to your request (within the thread pool where async IO operations are lodged) and so it won't be garbage collected until it completes."

但是,您的代码也在做它不需要做的事情:您不需要分离事件处理程序,也不需要在 web 客户端上调用 Dispose.(Dispose() 实际上不是由 WebClient 实现的——您可以在 http://referencesource.microsoft.com/netframework.aspx).

But, your code is also doing stuff it doesn't need to: you don't need to detach the event handler and don't need to call Dispose on the webclient. (Dispose() is actually not implemented by WebClient-- you can can see this in the .NET Framework reference source at http://referencesource.microsoft.com/netframework.aspx).

因此,您实际上不需要在回调中引用 webclient 实例.换句话说,以下代码也可以正常工作,并避免从委托内部引用外部局部变量的任何潜在问题(如上所述).

So you don't actually need to refer to the webclient instance in your callback. In other words, the following code will work just as well, and avoid any potential issues (discussed above) of referencing external local variables from inside a delegate.

private void DownloadData(Uri uri)
{
    WebClient webClient = new WebClient();
    DownloadDataCompletedEventHandler eh = null;
    eh = delegate(object sender, DownloadDataCompletedEventArgs e)
    {
        OnDataDownloaded();
    };
    webClient.DownloadDataCompleted += eh;
    webClient.DownloadDataAsync(uri);
}

无论如何,您可能想在别处寻找错误的来源.我要看的一个地方是 HTTP 调用的结果——您可能内存不足,可能遇到服务器错误等.您可以查看 e.Error 以查看调用是否实际工作.

Anyway, you probably want to look elsewhere for the source of your bug. One place I'd look is at the results of the HTTP calls-- you may be running out of memory, may be running into server errors, etc. You can look at e.Error to see if the calls are actually working.

这篇关于.NET:异步下载时是否需要保留对 WebClient 的引用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!

本文标题为:.NET:异步下载时是否需要保留对 WebClient 的引用?

基础教程推荐