多线程WebClient请求返回错误 - System.Net.WebException

时间:2014-05-12 12:14:59

标签: c# multithreading webclient

我想用WebClient下载5000多页。因为我希望尽可能快地完成,所以我尝试使用多线程(在我的情况下使用BlockingCollection),但程序似乎总是在一段时间后崩溃 - “System.Net.WebException”。如果我添加一些Thread.Sleep(3000)延迟,则会减慢我的下载过程,并且会在一段时间后返回错误。

下载一页通常需要2-3秒。

通常,我猜我的BlockingCollection存在问题,但它适用于其他任务,所以我很确定我的WebClient请求有些问题。我认为单独的WebClients之间可能存在某种重叠,但这只是猜测。

        Multithreading multiThread = new Multithreading(5); 
        for(int pageNumber = 1; pageNumber <= 5181; pageNumber++)
        {
            multiThread.EnqueueTask(new Action(() => //add task ("scrape the trader") to the multithread queue
            {
                using (WebClient client = new WebClient())
                {
                    client.DownloadFile("http://example.com/page=" + pageNumber.ToString(), @"C:\mypages\page " + pageNumber.ToString() + ".html");
                } 
            }));
            //I put the Thread.Sleep(123) delay here
        }

如果我添加一个较小的延迟(例如Thread.Sleep(100)),它可以正常工作,但最后我会抓取Page # *whatever pageNumber's value is at the moment*,而不是像往常一样。

这是我的BlockingCollection(我想我从stackoverflow获得了这个代码):

class Multithreading : IDisposable
{
      BlockingCollection<Action> _taskQ = new BlockingCollection<Action>();

      public Multithreading(int workerCount)
      {
        // Create and start a separate Task for each consumer:
        for (int i = 0; i < workerCount; i++)
          Task.Factory.StartNew (Consume);
      }

      public void Dispose() { _taskQ.CompleteAdding(); }

      public void EnqueueTask (Action action) { _taskQ.Add (action); }

      void Consume()
      {
        // This sequence that we’re enumerating will block when no elements
        // are available and will end when CompleteAdding is called. 
        foreach (Action action in _taskQ.GetConsumingEnumerable())
          action();     // Perform task.
      }
}

我还尝试将所有内容放入无限while循环并使用try...catch语句处理错误,但显然它不会立即返回错误,但过了一段时间(不确定何时)。

以下是完整的例外情况:

An exception of type 'System.Net.WebException' occurred in System.dll but was not handled in user code

Additional information: An exception occurred during a WebClient request.

1 个答案:

答案 0 :(得分:2)

不保证该类是线程安全的。来自MSDN:

  

不保证所有实例成员都是线程安全的

<强>更新

为您提出的每个请求使用一个HttpWebRequest。如果您向不同的网站提出了大量请求,那么使用WebClientHttpWebRequest并不重要。

如果你对同一网站做了很多请求,它仍然没有看起来那么低效。 HttpWebRequest重用连接(它隐藏在引擎盖下)。 Microsoft使用称为服务点的东西,您可以通过HttpWebRequest.ServicePoint属性访问它们。如果您单击属性定义,则可以转到ServicePoint documentation,您可以在其中微调每个网站的连接数等。