0

我曾经有:

using (MyWebClient client = new MyWebClient(TimeoutInSeconds))
{
   var res = client.DownloadData(par.Base_url);
   //code that checks res
}

我现在有:

using (MyWebClient client = new MyWebClient(TimeoutInSeconds))
{
   client.DownloadDataAsync(new Uri(par.Base_url));
   client.DownloadDataCompleted += (sender, e) =>
   {
       //code that checks e.Result
   }
}    

其中 MyWebClient 派生自 WebClient。现在我有很多线程在做这件事,在第一种情况下内存消耗不是问题,而在第二种情况下,我看到内存稳步上升,直到我得到 OutOfMemoryException。我进行了分析,似乎 WebClient 是罪魁祸首,没有被处理并保留下载的数据。但为什么?两种情况有什么区别?也许 e.Result 需要以某种方式处理?

4

2 回答 2

2

您的第一种情况将并发下载的数量限制为线程数。您的第二种情况对并发下载的数量没有限制。

于 2012-10-24T18:16:07.043 回答
0

您正在WebClient第二个选项中立即处理您的。你有几个选择:

  1. 如果您使用的是 .NET 4.5(或安装了 Visual Studio 2012 和 AsyncTargetingPack 的 .NET 4.0),您可以使用var res = await client.DownloadDataAsync(par.Base_url);与第一行类似但实际上是异步的代码。
  2. 使用正常的延续并摆脱你的using障碍

第一个选项如下所示:

using (MyWebClient client = new MyWebClient(TimeoutInSeconds))
{
   var res = await client.DownloadDataAsync(par.Base_url);
   //code that checks res
}

第二个选项如下所示:

var client = new MyWebClient(TimeoutInSeconds);

client.DownloadDataAsync(new Uri(par.Base_url))
    .ContinueWith(t =>
    {
        client.Dispose();

        var res = t.Result;

        //code that checks res
    }
}  

然而

您必须根据使用的解决方案更改线程方法。您的代码的第一个版本同步运行,因此如果您有一个专用于 URL 的线程(或连接,或者您正在拆分它们),下载将在该线程上同步运行并阻止它。但是,如果您选择其中任何一个选项,您最终将使用 IO 完成线程来完成您的工作,并将其从主线程中分离出来。从长远来看,这可能会更好,但这意味着您必须注意您并行提交的这些请求的数量。

于 2012-10-24T18:19:59.687 回答