Home > database >  C# Calculating download speed correctly when dowloading with multiple threads
C# Calculating download speed correctly when dowloading with multiple threads

Time:11-03

I'm trying to show to user correct download speed but my app downloads are bunch of small files at the same time and to speed things up I'm using Parallel.ForEach. However I can't calculate correct download speed. With my current code I'm basically calculating average download speed not the speed currently downloading. Because it updates UI every time download is completed. When I use normal foreach I can calculate correctly but then speed is slow. How can I show correctly the downloaded Mbps with multiple threads and multiple files ?

Note: This app is WPF but I hardly used any MVVM. This is my first time using WPF at the moment I'm just trying to make good looking something with decent functioning.

Download Function

var stopwatch = new Stopwatch();
            stopwatch.Start();
            DownloadController.stopwatch.Start();
            DownloadController.IsDownloadStarted = true;
            DownloadController.IsDownloadInProgress = true;
            Parallel.ForEach(downloadList, new ParallelOptions { MaxDegreeOfParallelism = 5 }, file =>
            {
                try
                {
                    DownloadController.LastDownloadingFileName = file.FileName;
                    GET_DownloadFile(file.FileName, file.LastUpdate.UnixTimeStampToDateTime()).GetAwaiter().GetResult();
                    logger.Info("Download", file.FileName, "Downloading file completed");
                }
                catch (Exception ex)
                {
                    lock (_failedDownloads)
                    {
                        _failedDownloads.Add(file);
                    }
                    logger.Exception(ex, "Download", file.FileName, file.LastUpdate, file.Size, $"Failed to download file");
                }
            });

Progress Changed Event

public static void DownloadProgressChangedEvent(object sender, DownloadProgressChangedEventArgs e)
        {

            MainWindow._dispatcher.BeginInvoke(new Action(() =>
            {
                ButtonProgressAssist.SetValue(MainWindow.This.Prog_Downloading, ProgressValue);
                ButtonController.ButtonPlay_Downloading();
                if (e.ProgressPercentage == 100)
                {
                    DownloadedSize  = e.TotalBytesToReceive;
                    var downloadSpeed = string.Format("{0} ", (DownloadedSize / 1024.0 / 1024.0 / stopwatch.Elapsed.TotalSeconds).ToString("0.0"));
                    var text1 = $"({ProgressValue}% - {DownloadedFileCount}/{TotalFileUpdateCount}) @ {downloadSpeed}MB/s {EasFile.GetFileNameWithExtension(LastDownloadingFileName)} ";
                    MainWindow.This.DownloadTextBlock.Text = text1;
                }
            }));

        }

ProgressCompletedEvent

public static void DownloadProgressCompletedEvent(object? sender, AsyncCompletedEventArgs e)
        {
            if (!e.Cancelled)
            {
                DownloadedFileCount  ;
            }
        }

I tried to use PerformanceCounter to watch my current app's network usage but it only shows me the usage of all usage on specific network.

CodePudding user response:

You have two choices here: First way is to create a class that will handle the single file downloading. In this class you should count the bytes downloaded. One possible solution for this is to have a member which is cleared every second. The received bytes should be added to it. Before it's clearing the class should report that value to the main class where it should be a member act in the same way for all currently downloading files. The other solution is instead of having a class on every progress event to report the received bytes and the time. In the main class you should have a list which will store that pairs. Then on every second you can get only the records for last second and aggregate the received bytes.

P.S. Accessing the members should be thread safe in both ways.

  • Related