在我的应用程序中,当您单击保存按钮时,它应该下载一个zip文件,同时显示进度,当下载完成时,它应该提取zip文件(使用DotNetZip lib)并继续进行。
当我测试它时,进度条会显示几秒钟的变化,然后冻结几秒钟并进入流程的最后阶段(提取已完成)。
到目前为止,这是我的代码:
// Handle nginx save action
private void saveNginX_Click(object sender, EventArgs e)
{
try
{
// Disable save button
(sender as Button).Enabled = false;
// Generate download & save file name
var downloadLink = new Uri(myNginXConfig.selected_resource.DownloadLink);
var saveFilename = @"apps\" + Path.GetFileName(downloadLink.AbsolutePath);
// Check if file already exists
if (File.Exists(saveFilename))
{
// Download completed, proceed to extracting
NginXDownloadCompleted();
}
else
{
// Update status
nginxStatus.Text = "Downloading " + selectNginX.SelectedItem.ToString() + " ...";
Thread.Sleep(1000);
// Init download
using (WebClient webClient = new WebClient())
{
webClient.DownloadProgressChanged += new DownloadProgressChangedEventHandler(NginXDownloadProgressChangedEvent);
webClient.DownloadFileCompleted += new AsyncCompletedEventHandler(NginXDownloadCompletedEvent);
webClient.DownloadFileAsync(downloadLink, saveFilename);
}
}
}
catch (Exception ex)
{
// Error
Utils.ShowError("Failed to save - " + ex.Message);
// Enable save button
(sender as Button).Enabled = true;
}
}
// Handle nginx download progress changed event
private void NginXDownloadProgressChangedEvent(object sender, DownloadProgressChangedEventArgs e)
{
// Update the progressbar percentage only when the value is not the same.
nginxProgress.Value = e.ProgressPercentage;
// Calculate download progresss
var downloadProgress = string.Format("{0} MB / {1} MB",
(e.BytesReceived / 1024d / 1024d).ToString("0.00"),
(e.TotalBytesToReceive / 1024d / 1024d).ToString("0.00"));
// Update download progress
nginxStatus.Text = "Downloading " + downloadProgress + " ...";
}
// Handle nginx download complete event
private void NginXDownloadCompletedEvent(object sender, AsyncCompletedEventArgs e)
{
if (e.Cancelled != true)
NginXDownloadCompleted();
}
// Handle nginx download complete
private void NginXDownloadCompleted()
{
// Update status
nginxStatus.Text = "Download completed; extracting ...";
nginxStatus.Update();
Thread.Sleep(1000);
nginxProgress.Value = 0;
// Generate download & save file name
var downloadLink = new Uri(myNginXConfig.selected_resource.DownloadLink);
var saveFilename = @"apps\" + Path.GetFileName(downloadLink.AbsolutePath);
// Begin extracting the downloaded zip file
using (ZipFile zip = ZipFile.Read(saveFilename))
{
zip.ExtractProgress += new EventHandler<ExtractProgressEventArgs>(NginXExtractProgressEvent);
zip.ExtractAll("apps", ExtractExistingFileAction.OverwriteSilently);
}
// Json encode setting and save it
// File.WriteAllText(@"apps\NginXConfig.json", JsonConvert.SerializeObject(myNginXConfig, Formatting.Indented));
}
// Handle nginx extract progress event
private void NginXExtractProgressEvent(object sender, ExtractProgressEventArgs e)
{
if (e.TotalBytesToTransfer > 0)
nginxProgress.Value = Convert.ToInt32(100 * e.BytesTransferred / e.TotalBytesToTransfer);
if (e.EventType == ZipProgressEventType.Extracting_AfterExtractAll)
NginXExtractCompleted();
}
// Handle nginx extract completed event
private void NginXExtractCompleted()
{
// Update status
nginxStatus.Text = "Extracting completed; generating config ...";
nginxStatus.Update();
Thread.Sleep(1000);
nginxProgress.Value = 0;
}
状态标签文本似乎也在做同样的事情。感觉/看起来好像过程不同步,它只是跳跃。
我尝试过使用Label.Update()
方法,但这并没有帮助。
任何想法我可能做错了什么?
我希望在事件发生时以程序方式报告UI上状态更新的进度。
答案 0 :(得分:0)
问题在于NginXDownloadCompleted方法。虽然DownloadFileAsync是异步方法,但ExtractAll不是,因此您的代码从Internet异步下载文件,但在文件提取时冻结主线程。
你需要的是 - 创建单独的后台线程(使用任何可用的选项:通过Thread类,通过ThreadPool,通过Tasks),并以同步的方式完成在此线程中下载和解压缩的全部工作。
一些注意事项: