【问题标题】:C# Calculating download speed correctly when dowloading with multiple threadsC#使用多线程下载时正确计算下载速度
【发布时间】:2022-11-02 22:06:59
【问题描述】:

我试图向用户展示正确的下载速度,但我的应用程序下载同时是一堆小文件,为了加快速度,我正在使用Parallel.ForEach。但是我无法计算正确的下载速度。使用我当前的代码,我基本上是在计算平均下载速度,而不是当前下载的速度。因为每次下载完成时它都会更新 UI。当我使用正常的foreach 时,我可以正确计算但速度很慢。如何使用多个线程和多个文件正确显示下载的 Mbps?

注意:这个应用程序是 WPF,但我几乎没有使用任何 MVVM。这是我第一次使用 WPF,目前我只是想制作一个功能不错的东西。

下载功能

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

进度改变事件

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

        }

进度完成事件

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

我尝试使用PerformanceCounter 来查看我当前应用程序的网络使用情况,但它只显示特定网络上所有使用情况的使用情况。

【问题讨论】:

  • 只需打印“大约剩下三个烦人”,以一秒的增量将进度条增加到 90%,完成后将其移动到 100%。这是一个几十年前的问题,你无法解决。如果您事先不知道需要下载多少字节,则永远无法给出准确的估计。
  • 您可以创建一个Progress 类并以线程安全的方式跟踪此类中总下载字节的状态,但除非您的下载需要很长时间,否则在 UI 中显示一个不确定的进度条通常就足够了。
  • @CodeCaster 我确实知道每次下载将有多少字节。
  • @mcy 主要下载大约 20 300MB 大约 20 个文件。但客户端也可以一次下载大约 7000+ 个文件,具体取决于客户端是否拥有所有文件。
  • 那么,保持每个文件的进度?

标签: c# .net wpf


【解决方案1】:

您在这里有两个选择: 第一种方法是创建一个处理单个文件下载的类。在这个类中,您应该计算下载的字节数。一种可能的解决方案是让一个成员每秒被清除一次。应将接收到的字节添加到其中。在清除之前,该类应该将该值报告给它应该成为成员的主类,对所有当前下载的文件以相同的方式进行操作。 另一种解决方案不是在每个进度事件上都有一个类来报告接收到的字节和时间。在主类中,您应该有一个存储这些对的列表。然后每一秒你只能得到最后一秒的记录并聚合接收到的字节。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-05-16
    • 2010-09-27
    • 2012-05-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-04
    • 2014-05-22
    相关资源
    最近更新 更多