你处理这一切都是错误的。如果你想下载 3000 或更多的页面,你必须更有效率,而不是等待每次下载的事件。
实施(只是一个草稿,你必须完成它)
public class Downloader
{
ConcurrentQueue<Uri> _queue = new ConcurrentQueue<Uri>();
int _maxWorkers = 10;
long _currentWorkers = 0;
ManualResetEvent _completed;
public void Enqueue(Uri uri)
{
_queue.Enqueue(uri);
if (Interlocked.Read(_currentWorkers) < _maxWorkers)
{
// not very thread safe, but we just want to limit the workers
// within a reasonable limit. 1 or 2 more doesn't really matter.
Interlocked.Increment(_currentWorkers);
// yes, i'm a bit old fashioned.
TriggerJob();
}
}
private void TriggerJob()
{
Uri uri;
if (!_queue.TryDequeue(out uri))
{
Interlocked.Decrement(_currentWorkers);
return;
}
var client = new WebClient();
client.Encoding = Encoding.UTF8;
client.DownloadDataCompleted += DownloadDataCompleted;
client.DownloadDataAsync(uri);
}
private void DownloadDataCallback(object sender, DownloadDataCompletedEventArgs e)
{
try
{
// If the request was not canceled and did not throw
// an exception, display the resource.
if (!e.Cancelled && e.Error == null)
{
var args = new DownloadedEventArgs { uri = e.Uri, data = (byte[])e.result};
DownloadCompleted(this, args)
}
else
{
var args = new DownloadFailedEventArgs { uri = e.Uri, error = e.Error };
DownloadFailed(this, args);
}
}
catch (Exception err)
{
var args = new DownloadFailedEventArgs { uri = e.Uri, error = err };
DownloadFailed(this, args);
}
TriggerJob();
}
public event EventHandler<DownloadedEventArgs> DownloadCompleted = delegate{};
public event EventHandler<DownloadFailedEventArgs> DownloadFailed = delegate{};
}
public class DownloadedEventArgs
{
public Uri uri;
public byte[] data;
}
public class DownloadFailedEventArgs
{
public Uri uri;
public Exception error;
}
用法:
var downloader = new Downloader();
downloader.Completed += (o,e) { Console.WriteLine("Whoohoho, completed: " + e.Uri); };
for (x = 1; x < 100000; x++)
{
downloader.Enqueue(new Uri("http://somewhere.com));
}