C# 多个WebClient完成得非常慢

C# 多个WebClient完成得非常慢,c#,.net,multithreading,webclient,C#,.net,Multithreading,Webclient,我有一个类可以在多个线程上同时创建多个具有不同代理的WebClient类 不幸的是,WebClient类的某些实例需要很长时间才能完成。通常情况下,我会得到大约20个线程,需要几分钟才能完成。另一方面,我产生了数百个线程,它们完成得很快 我试图创建并扩展WebClient类,并将Timeout属性设置为20秒(),但没有改变任何内容 我不会展示全部代码,因为其中会有很多(WebClient包装在另一个类中)。不过,我知道瓶颈是WebClient.DownloadString(url),因为每当我

我有一个类可以在多个线程上同时创建多个具有不同代理的
WebClient

不幸的是,
WebClient
类的某些实例需要很长时间才能完成。通常情况下,我会得到大约20个线程,需要几分钟才能完成。另一方面,我产生了数百个线程,它们完成得很快

我试图创建并扩展
WebClient
类,并将Timeout属性设置为20秒(),但没有改变任何内容

我不会展示全部代码,因为其中会有很多(
WebClient
包装在另一个类中)。不过,我知道瓶颈是
WebClient.DownloadString(url)
,因为每当我在执行代码的最后一步暂停调试时,所有工作线程都在处理这一特定行

下面是我如何使用扩展的
WebClient

public string GetHtml(string url)
{
    this.CheckValidity(url);

    var html = "";

    using (var client = new WebDownload())
    {
        client.Proxy = this.Proxy;
        client.Headers[HttpRequestHeader.UserAgent] = this.UserAgent;
        client.Timeout = this.Timeout;

        html = client.DownloadString(url);
    }

    return html;
 }
编辑

我刚刚运行了一些测试,其中一些线程需要7分钟才能完成,所有这些都考虑了
WebClient.DownloadString()
语句


此外,我还尝试将
ServicePointManager.DefaultConnectionLimit
设置为
int.MaxValue
,可惜没有成功。

以下是我最后的做法

我意识到问题是,当WebClient.DownloadString()达到指定的超时时,我只需取消它。由于我在
WebClient
中没有找到任何对我有帮助的东西,所以我只调用了
WebClient.downloadstringtaskancy()
。这样,我可以使用带有超时的
Task.WaitAll
来等待
WebClient
完成字符串下载,然后检查任务是否已完成(以排除超时)

代码如下:

public string GetHtml(string url)
{
    var html = "";

    using (var client = new WebClient())
    {
        // Assign all the important stuff
        client.Proxy = this.Proxy;
        client.Headers[HttpRequestHeader.UserAgent] = this.UserAgent;

        // Run DownloadString() as a task.
        var task = client.DownloadStringTaskAsync(url);

        // Wait for the task to finish, or timeout
        Task.WaitAll(new Task<string>[] { task }, this.Timeout);

        // If timeout was reached, cancel task and throw an exception.
        if (task.IsCompleted == false)
        {
            client.CancelAsync();
            throw new TimeoutException();
        }

        // Otherwise, happy. :)
        html = task.Result;
    }
publicstringgethtml(字符串url)
{
var html=“”;
使用(var client=new WebClient())
{
//分配所有重要的东西
client.Proxy=this.Proxy;
client.Headers[HttpRequestHeader.UserAgent]=this.UserAgent;
//将DownloadString()作为任务运行。
var task=client.downloadstringtasksync(url);
//等待任务完成或超时
Task.WaitAll(新任务[]{Task},this.Timeout);
//若达到超时,则取消任务并引发异常。
如果(task.IsCompleted==false)
{
client.CancelAsync();
抛出新的TimeoutException();
}
//否则,我会很高兴的
html=task.Result;
}

您是否在没有线程的情况下尝试过此操作以了解预期的响应时间?它们是否都来自同一台主机?@brumcouse,是的,我尝试过。我相信问题可能在于提供的代理的质量。如果我可以简单地为整个操作设置超时,那就太好了。我想我可以使用
do来完成此操作wnloadStringAsync
,等待它完成并在提供的超时后引发异常(我刚刚想到了:D)。但这是个好主意吗?@JonSkeet,请注意!是的,但是每个请求都使用不同的代理,所以这应该不会是个问题。(我猜?)@moskalak:老实说,我不知道连接池在这些方面是如何工作的。涉及到多少不同的代理,而不是多少请求?