【问题标题】:e.ProgressPercentage returns 0-50e.ProgressPercentage 返回 0-50
【发布时间】:2018-09-05 13:45:26
【问题描述】:

我有以下监控上传过程的代码。我正在使用e.ProgressPercentage 跟踪当前进度,但它返回了错误的值。

using (WebClient client = new WebClient())
{
    client.Credentials = new NetworkCredential(DataIO.FTP.Username, DataIO.FTP.Password);

    Uri uri = new Uri($"ftp://{DataIO.FTP.Server}/{DataIO.FTP.UploadDir}/{DataIO.SelectedOutputArchive}.tar.gz");

    client.UploadProgressChanged += new UploadProgressChangedEventHandler(delegate (object s2, UploadProgressChangedEventArgs e2) {

        ProgressLabel.Invoke((MethodInvoker)delegate
        {
            ProgressLabel.Text = $"{(e2.BytesSent / 1024).ToString()} KB / {(e2.TotalBytesToSend / 1024).ToString()} KB";
        });

        UploadProgressBar.Invoke((MethodInvoker)delegate
        {
            UploadProgressBar.Value = e2.ProgressPercentage; // returns 0-50
            //UploadProgressBar.Value = (int)Clamp((float)e2.ProgressPercentage / 50 * 100, 0, 100);
        });

        Debug.WriteLine(e2.ProgressPercentage);
    });

    client.UploadFileCompleted += new UploadFileCompletedEventHandler(delegate {
        this.Invoke((MethodInvoker)delegate
        {
            this.Text = "Upload: Success";
        });

        Thread.Sleep(2000);

        this.Invoke((MethodInvoker)delegate
        {
            this.Close();
        });

    });

    client.UploadFileAsync(uri, "STOR", localFilePath);
}

我尝试在输出窗口调试它,它返回的值是这样的:

0
0
1
0
1
0
1
1
1
2
2
1
2
2
3
3
2
3
3
...
49
49
50
49
100
49
49

这些后跳不一定重要,但从 49 跳到 100 很重要。

我假设它总是在 0-50 之间返回(在意识到它不会从 50 上升之后)。所以我需要将它缩放到 0-100。这行得通,但随后它从 49 跃升至 100。缩放期望数字从 0-50,并且接收 100 打破它(导致溢出(200),进度条期望 0-100)。然后我不得不钳制结果值。所以我想出了这个:

(int)Clamp((float)e2.ProgressPercentage / 50 * 100, 0, 100)

虽然现在这可以正常工作,但我想知道为什么我需要破解我的方法才能使其正常工作。我做错了吗?


更新:我决定不依赖e.ProgressPercentage,自己计算:

UploadProgressBar.Value = (int)(e2.BytesSent / (float)e2.TotalBytesToSend * 100);

【问题讨论】:

    标签: c# file-upload ftp webclient


    【解决方案1】:

    这是设计使然。原因是

    当您进行上传时,服务器也可以发送数据作为对上传的响应。一般来说,任何 HTTP 请求都是如此。考虑一个上传一堆输入的表单,而服务器发送一大堆数据,可能是一个 SQL 服务器数据库报告。 在所有这些情况下,我们将上传和下载分为 50% 和 50%。 所以如果服务器没有发送任何数据,那么它会直接从 50 跳转到 100

    来源:https://social.msdn.microsoft.com/Forums/en-US/9ab5a1b4-c30d-4dbb-bebe-a00ef8e72029/problems-with-webclientuploadfileasync?forum=netfxnetcom

    还要检查 this thread 以了解此方法可能存在的问题。

    另一种解决方案

    另一个可视化上传正确值的选项是使用 UploadProgressChangedEventArgs 对象的另外两个属性 - BytesSent、TotalBytesToSend - 并自己进行计算。如需参考,请查看the examples section

    编辑: 我找不到任何地方记录以这种方式实现它的原因是什么,但这里是负责这种行为的代码:

            private void PostProgressChanged(AsyncOperation asyncOp, ProgressData progress) {
            if (asyncOp != null && progress.BytesSent + progress.BytesReceived > 0)
            {
                int progressPercentage;
                if (progress.HasUploadPhase)
                {
                    if (progress.TotalBytesToReceive < 0 && progress.BytesReceived == 0)
                    {
                        progressPercentage = progress.TotalBytesToSend < 0 ? 0 : progress.TotalBytesToSend == 0 ? 50 : (int)((50 * progress.BytesSent) / progress.TotalBytesToSend);
                    }
                    else
                    {
                        progressPercentage = progress.TotalBytesToSend < 0 ? 50 : progress.TotalBytesToReceive == 0 ? 100 : (int) ((50 * progress.BytesReceived) / progress.TotalBytesToReceive + 50);
                    }
                    asyncOp.Post(reportUploadProgressChanged, new UploadProgressChangedEventArgs(progressPercentage, asyncOp.UserSuppliedState, progress.BytesSent, progress.TotalBytesToSend, progress.BytesReceived, progress.TotalBytesToReceive));
                }
                else
                {
                    progressPercentage = progress.TotalBytesToReceive < 0 ? 0 : progress.TotalBytesToReceive == 0 ? 100 : (int) ((100 * progress.BytesReceived) / progress.TotalBytesToReceive);
                    asyncOp.Post(reportDownloadProgressChanged, new DownloadProgressChangedEventArgs(progressPercentage, asyncOp.UserSuppliedState, progress.BytesReceived, progress.TotalBytesToReceive));
                }
            }
        }
    

    来源:https://referencesource.microsoft.com/System/net/System/Net/webclient.cs.html#2966

    【讨论】:

    • 它并没有解释下降。
    • 此设计/行为是否记录在案?我想阅读更多。另外,我现在决定自己计算百分比。干净多了。
    • 我编辑了我之前的答案,并包含了一个用于代码参考的 URL (referencesource.microsoft.com/System/net/System/Net/…)。但不幸的是,我找不到任何文档说明它为什么会这样工作。
    【解决方案2】:

    我能够重现同样的情况,包括奇怪的掉落。

    考虑使用来自单独线程的FtpWebRequest。这样,您就可以完全控制上传进度。

    查看我的回答 How can we show progress bar for upload with FtpWebRequest.

    【讨论】:

      猜你喜欢
      • 2016-12-07
      • 2013-09-08
      • 1970-01-01
      • 2015-06-15
      • 1970-01-01
      • 2018-03-22
      • 2019-05-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多