有没有比忙碌等待更智能的方法来检查System.Net.WebClient.DownloadFileAsync()的下载完成情况?

时间:2011-04-17 01:12:21

标签: c# .net

我正在使用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);
    }
}

3 个答案:

答案 0 :(得分:8)

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();
}

答案 1 :(得分:5)

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

答案 2 :(得分:0)

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触发时设置通知程序。如果下载过程中文件错误,这将阻止线程挂起。

参考:WebClient DownloadFileAsync hangs