很难找到使用webclient类异步方法下载多个文件的代码示例,但一次只下载一个。
如何启动异步下载,但要等到第一次完成,直到第二次,等等。基本上是一个阙。
(注意我不想使用同步方法,因为异步方法的功能增加了。)
以下代码会立即启动所有下载。 (进度条到处都是)
private void downloadFile(string url)
{
WebClient client = new WebClient();
client.DownloadProgressChanged += new DownloadProgressChangedEventHandler(client_DownloadProgressChanged);
client.DownloadFileCompleted += new AsyncCompletedEventHandler(client_DownloadFileCompleted);
// Starts the download
btnGetDownload.Text = "Downloading...";
btnGetDownload.Enabled = false;
progressBar1.Visible = true;
lblFileName.Text = url;
lblFileName.Visible = true;
string FileName = url.Substring(url.LastIndexOf("/") + 1,
(url.Length - url.LastIndexOf("/") - 1));
client.DownloadFileAsync(new Uri(url), "C:\\Test4\\" + FileName);
}
void client_DownloadFileCompleted(object sender, AsyncCompletedEventArgs e)
{
}
void client_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
{
double bytesIn = double.Parse(e.BytesReceived.ToString());
double totalBytes = double.Parse(e.TotalBytesToReceive.ToString());
double percentage = bytesIn / totalBytes * 100;
progressBar1.Value = int.Parse(Math.Truncate(percentage).ToString());
}
答案 0 :(得分:35)
我所做的是填充包含所有网址的队列,然后下载队列中的每个项目。当没有剩余物品时,我可以处理所有物品。我在下面嘲笑了一些代码。请记住,下面的代码用于下载字符串而不是文件。修改下面的代码应该不会太难。
private Queue<string> _items = new Queue<string>();
private List<string> _results = new List<string>();
private void PopulateItemsQueue()
{
_items.Enqueue("some_url_here");
_items.Enqueue("perhaps_another_here");
_items.Enqueue("and_a_third_item_as_well");
DownloadItem();
}
private void DownloadItem()
{
if (_items.Any())
{
var nextItem = _items.Dequeue();
var webClient = new WebClient();
webClient.DownloadStringCompleted += OnGetDownloadedStringCompleted;
webClient.DownloadStringAsync(new Uri(nextItem));
return;
}
ProcessResults(_results);
}
private void OnGetDownloadedStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
if (e.Error == null && !string.IsNullOrEmpty(e.Result))
{
// do something with e.Result string.
_results.Add(e.Result);
}
DownloadItem();
}
修改强> 我已修改您的代码以使用队列。不完全确定你希望如何进步。我确定您是否希望进度能够满足所有下载,然后您可以将项目计数存储在'PopulateItemsQueue()'方法中,并在进度更改方法中使用该字段。
private Queue<string> _downloadUrls = new Queue<string>();
private void downloadFile(IEnumerable<string> urls)
{
foreach (var url in urls)
{
_downloadUrls.Enqueue(url);
}
// Starts the download
btnGetDownload.Text = "Downloading...";
btnGetDownload.Enabled = false;
progressBar1.Visible = true;
lblFileName.Visible = true;
DownloadFile();
}
private void DownloadFile()
{
if (_downloadUrls.Any())
{
WebClient client = new WebClient();
client.DownloadProgressChanged += client_DownloadProgressChanged;
client.DownloadFileCompleted += client_DownloadFileCompleted;
var url = _downloadUrls.Dequeue();
string FileName = url.Substring(url.LastIndexOf("/") + 1,
(url.Length - url.LastIndexOf("/") - 1));
client.DownloadFileAsync(new Uri(url), "C:\\Test4\\" + FileName);
lblFileName.Text = url;
return;
}
// End of the download
btnGetDownload.Text = "Download Complete";
}
private void client_DownloadFileCompleted(object sender, AsyncCompletedEventArgs e)
{
if (e.Error != null)
{
// handle error scenario
throw e.Error;
}
if (e.Cancelled)
{
// handle cancelled scenario
}
DownloadFile();
}
void client_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
{
double bytesIn = double.Parse(e.BytesReceived.ToString());
double totalBytes = double.Parse(e.TotalBytesToReceive.ToString());
double percentage = bytesIn / totalBytes * 100;
progressBar1.Value = int.Parse(Math.Truncate(percentage).ToString());
}
答案 1 :(得分:2)
我正在努力了解问题所在。如果你只为第一个文件调用异步方法,它不会只下载该文件吗?为什么不使用client_downlaodFileCompleted事件根据AsyncCompletedEvents传递的某个值启动下一个文件下载,或者将下载的文件列表保存为静态变量,并使用client_DownloadFileCompleted迭代列表以查找要下载的下一个文件。
希望有所帮助,但如果我对您的问题有所了解,请发布更多信息。
答案 2 :(得分:1)
我会创建一个新方法,例如名为getUrlFromQueue,它从队列(集合或数组)返回一个新url并删除它..然后它调用downloadFile(url) - 并在client_DownloadFileCompleted中再次调用getUrlFromQueue。 / p>