我想用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.
答案 0 :(得分:2)
不保证该类是线程安全的。来自MSDN:
不保证所有实例成员都是线程安全的
<强>更新强>
为您提出的每个请求使用一个HttpWebRequest
。如果您向不同的网站提出了大量请求,那么使用WebClient
或HttpWebRequest
并不重要。
如果你对同一网站做了很多请求,它仍然没有看起来那么低效。 HttpWebRequest
重用连接(它隐藏在引擎盖下)。 Microsoft使用称为服务点的东西,您可以通过HttpWebRequest.ServicePoint属性访问它们。如果您单击属性定义,则可以转到ServicePoint
documentation,您可以在其中微调每个网站的连接数等。