简体   繁体   中英

WebClient.DownloadFileAsync - How do I keep track of the total amount of bytes downloaded when downloading multiple files?

So I'm trying to download two images and just for demonstration I've checked their sizes and summed it up to a variable called totalBytes .

I want to keep track of how much has been downloaded out of those total bytes so I can calculate the percentage by taking downloaded / totalBytes * 100

But I have no idea how to keep track of the mount of bytes that has been downloaded.

public static int totalBytes = 1378954;
static void Main(string[] args)
{
    var images = new List<string>
    {
        "http://4.bp.blogspot.com/-HTvSYzA-pO4/UgQb4Zh_u0I/AAAAAAAAEuI/XwhtogT_1tA/s1600/3+cute2.jpg",
        "http://getwallpapers.com/wallpaper/full/7/7/0/74728.jpg"
    };
    foreach (var image in images)
    {
        int i = 0;
        using (var wc = new WebClient())
        {
            wc.DownloadProgressChanged += Wc_DownloadProgressChanged;
            wc.DownloadFileAsync(new Uri(image), $"image{i}.png");
            i++;

            Console.ReadKey();
        }

    }
}

private static void Wc_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
{
    Console.WriteLine($"Downloaded: {e.BytesReceived} out of {totalBytes}");
}

Assuming that you do not intend to actually start downloading files in parallel (as you dispose the WebClient before starting another download), the problem can be solved with two field

  1. One to store the current total
  2. Another to store the previous ReceivedByte value

     private static long _totalBytesReceivedAllFiles = 0; private static long _previousBytesReceivedForCurrentFile = 0; private static object _lock = new Object(); private static void Wc_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e) { // There are no guarantees in the documentation that such events are serialized and can't execute in parallel even for a single file, // thus we will use lock to at least partially serialize it and ensure atomic field access. // !!!It is not intended to handle actual parallel downloads!!! lock (_lock) { _totalBytesReceivedAllFiles = _totalBytesReceivedAllFiles - _previousBytesReceivedForCurrentFile + e.BytesReceived; _previousBytesReceivedForCurrentFile = e.BytesReceived; Console.WriteLine($"Downloaded: {_totalBytesReceivedAllFiles} out of {totalBytes}"); if (e.ProgressPercentage == 100) { Console.WriteLine("Current file downloaded"); _previousBytesReceivedForCurrentFile = 0; } } } 

If on the other hand you want to start downloads truly in parallel, then you will have to

  1. Not to dispose (in the loop!) the client, for obvious reasons.
  2. Use a per-file Wc_DownloadProgressChanged with closure to have an actual per-file _previousBytesReceivedForCurrentFile

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM