我试图从我的网络服务器下载文件夹,我想在进度条上显示已下载的数据量/要下载的总数量。首先,我尝试使用WebClient.DownloadFile
。哪个完美无瑕,但它并没有触发DownloadProgressChangedEventHandler
。我猜它只能通过异步下载激活。所以我将我的方法改写为WebClient.DownloadFileAsync
。这是它变得复杂的地方。
例如,我的Web服务器上有30个文件,大小为53 MB。我想下载所有30个文件并在进度条上显示下载的进度(并在其下显示带有xx / 53 MB下载的标签)。
//Inicialized by opening dialog
private void DownloadForm_Shown(object sender, EventArgs e) {
WebClient client = new WebClient();
client.DownloadProgressChanged += client_DownloadProgressChanged;
client.DownloadFileCompleted += client_DownloadFileCompleted;
startDownload();
}
void client_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e) {
progressBar.Value = e.ProgressPercentage;
labelProgress.Text = String.Format("Downloaded {0} of {1} bytes", e.BytesReceived, e.TotalBytesToReceive);
}
private void startDownload() {
//files contains all URL links
foreach (string str in files) {
string urlDownload = HttpUtility.UrlPathEncode(str);
//location is variable where file will be stored
client.DownloadFileAsync(new Uri(urlDownload), location);
//without this, async download will go crazy and wont download anything
while (client.IsBusy) { }
}
}
我有这个代码,它发生了什么,它将开始下载,但它不会更新进度条,也不会更新标签。下载后,它将在大约0.5秒内更新进度和标签,这就是它。我是这类人的初学者,你能帮我找一个错误吗?我知道如何为一个文件创建进度条。但我要做的是为多个文件制作它?
编辑:可以在此处找到包含某些解决方案的完整代码:http://pastebin.com/Hu4CCY8M
但是在调用downloadURLs()
方法后,UI将冻结。完成此方法后它将再次开始工作。
答案 0 :(得分:3)
如果没有可靠地再现问题的好Minimal, Complete, and Verifiable code example,就不可能完全解决问题。也就是说,从你发布的代码中可以清楚地看出,这里的主要问题是你已经阻止了UI线程,阻止了进度条的任何更改在下载过程中反映在用户界面上。
WebClient
对象沿“WebClient不支持并发I / O操作”抛出异常 。如果你想(也许你应该想要)同时下载文件,你需要有多个WebClient
对象,每个并发下载一个。
鉴于您明确意图一次下载一个文件,您需要这样做而不会阻止UI线程。您发布的代码甚至可能不是原始代码的精确复制/粘贴,因为您在client
方法中使用标识符startDownload()
而不在任何地方声明,并且没有它可能是与client
方法中的局部变量DownloadForm_Shown()
相同。因此,暂时忽略这种差异,这里是您发布的代码的变体,它将名义上解决您的问题:
private TaskCompletionSource<bool> _tcs;
private async void DownloadForm_Shown(object sender, EventArgs e) {
WebClient client = new WebClient();
client.DownloadProgressChanged += client_DownloadProgressChanged;
client.DownloadFileCompleted += client_DownloadFileCompleted;
await startDownload(client);
}
void client_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e) {
progressBar.Value = e.ProgressPercentage;
labelProgress.Text = String.Format("Downloaded {0} of {1} bytes", e.BytesReceived, e.TotalBytesToReceive);
}
void client_DownloadFileCompleted(object sender, DownloadFileCompletedEventArgs e) {
// whatever else you have in this event handler, and then...
_tcs.SetResult(true);
}
private async Task startDownload(WebClient client) {
//files contains all URL links
foreach (string str in files) {
string urlDownload = HttpUtility.UrlPathEncode(str);
//location is variable where file will be stored
_tcs = new TaskCompletionSource<bool>();
client.DownloadFileAsync(new Uri(urlDownload), location);
await _tcs.Task;
}
_tcs = null;
}
这样,DownloadForm_Shown()
方法将在下载进行时将控制权返回给UI线程。每个下载的文件完成后,执行将在startDownload()
方法中恢复,以便下一个文件可以启动。
如果上述内容无法让您回到正轨,请改进问题,使其包含良好的MCVE和更准确的问题说明。