是否有比忙碌等待检查System.Net.WebClient.DownloadFileAsync()下载完成更聪明的方法

本文关键字:下载 方法 更聪明 DownloadFileAsync WebClient 等待 Net System 检查 是否 | 更新日期: 2023-09-27 17:50:27

我正在使用System.Net.WebClient.DownloadFileAsync()下载文件。使用异步版本的唯一原因是显示下载的进度。在达到100%之前,我的代码执行可能无法继续。目前我正在使用一个繁忙等待(见代码),但我想知道是否有一个更聪明的方法来做到这一点。

using(WebClient oWebClient = new WebClient())
{
    oWebClient.Encoding = System.Text.Encoding.UTF8;
    long lReceived = 0;
    long lTotal = 0;
    // Set up a delegate to watch download progress.
    oWebClient.DownloadProgressChanged += delegate(object sender, DownloadProgressChangedEventArgs e)
    {
        Console.WriteLine(e.ProgressPercentage + "% (" + e.BytesReceived / 1024f + "kb of " + e.TotalBytesToReceive / 1024f + "kb)");
            // Assign to outer variables to allow busy-wait to check.
        lReceived = e.BytesReceived;
        lTotal = e.TotalBytesToReceive;
    };
    oWebClient.DownloadFileAsync(new Uri(sUrl + "?" + sPostData), sTempFile);
    while(lReceived == 0 || lReceived != lTotal)
    {
           // Busy wait.
        Thread.Sleep(1000);
    }
}

是否有比忙碌等待检查System.Net.WebClient.DownloadFileAsync()下载完成更聪明的方法

using(WebClient oWebClient = new WebClient())
{
    // use an event for waiting, rather than a Thread.Sleep() loop.
    var notifier = new AutoResetEvent(false);
    oWebClient.Encoding = System.Text.Encoding.UTF8;
    long lReceived = 0;
    long lTotal = 0;
    // Set up a delegate to watch download progress.
    oWebClient.DownloadProgressChanged += delegate(object sender, DownloadProgressChangedEventArgs e)
    {
        Console.WriteLine(e.ProgressPercentage + "% (" + e.BytesReceived / 1024f + "kb of " + e.TotalBytesToReceive / 1024f + "kb)");
        // Assign to outer variables to allow busy-wait to check.
        lReceived = e.BytesReceived;
        lTotal = e.TotalBytesToReceive;
        // Indicate that things are done
        if(lReceived >= lTotal) notifier.Set();
    };
    oWebClient.DownloadFileAsync(new Uri(sUrl + "?" + sPostData), sTempFile);
    // wait for signal to proceed
    notifier.WaitOne();
}

使用AutoResetEvent。在DownloadFileCompleted事件处理程序中调用它的Set()方法,在DownloadFileAsync()调用之后调用它的WaitOne()方法。

using(WebClient oWebClient = new WebClient())
{
    // use an event for waiting, rather than a Thread.Sleep() loop.
    var notifier = new AutoResetEvent(false);
    oWebClient.Encoding = System.Text.Encoding.UTF8;
    long lReceived = 0;
    long lTotal = 0;
    // Set up a delegate to watch download progress.
    oWebClient.DownloadProgressChanged += delegate(object sender, DownloadProgressChangedEventArgs e)
    {
        Console.WriteLine(e.ProgressPercentage + "% (" + e.BytesReceived / 1024f + "kb of " + e.TotalBytesToReceive / 1024f + "kb)");
        // Assign to outer variables to allow busy-wait to check.
        lReceived = e.BytesReceived;
        lTotal = e.TotalBytesToReceive;
    };
    // Set a delegate to watch for when the download is complete
      oWebClient.OpenReadCompleted += delegate(object sender, OpenReadCompletedEventArgs e)
    {
         // Indicate that things are done
         notifier.Set();
    };
    oWebClient.DownloadFileAsync(new Uri(sUrl + "?" + sPostData), sTempFile);
    // wait for signal to proceed
    notifier.WaitOne();
}

我已经扩展了@OJ的答案,在OpenReadCompleted触发时设置通知器。如果文件在下载过程中出现错误,这将阻止线程挂起。

Ref: WebClient DownloadFileAsync hang