我的后台工作者报告超过100%

时间:2013-11-30 07:23:10

标签: c#

我正在编写一个复制文件的程序。我有正确的文件复制,进度条更新,但我收到一个错误,指出e.ProgressPercentage是101. bgWorker_ProgressChanged事件处理程序的代码是:

private void bgWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        // We will increase the progress bar when work progress is reported.
                    pbCopyProgress.Maximum = 100;
        pbCopyProgress.Value = e.ProgressPercentage;        
    }

以下是bgWorker_DoWork事件处理程序的代码:

private void bgWorker_DoWork(object sender, DoWorkEventArgs e)
    {
        // Gets the size of the file in bytes.
        Int64 iSize = strInputFile.Length;

        // Keeps track of the total bytes downloaded so we can update the progress bar.
        Int64 iRunningByteTotal = 0;
            // Open the input file for reading.
        using (FileStream InputFile = new FileStream(strInputFile, FileMode.Open, FileAccess.Read, FileShare.None))
        {
            // Using the FileStream object, we can write the output file.
            using (FileStream OutputFile = new FileStream(strOutputFile, FileMode.Create, FileAccess.Write, FileShare.None))
            {
                // Loop the stream and get the file into the byte buffer.
                int iByteSize = 0;
                byte[] byteBuffer = new byte[iSize];

                while ((iByteSize = InputFile.Read(byteBuffer, 0, byteBuffer.Length)) > 0)                    
                {
                    // Calculate the progress out of a base "100."
                    double dIndex;
                    double dTotal;
                    double dProgressPercentage;
                    // Write the bytes to the file system at the file path specified.                        
                    dIndex = (double)(iRunningByteTotal);
                    dTotal = (double)byteBuffer.Length;
                    dProgressPercentage = (dIndex / dTotal);
                    OutputFile.Write(byteBuffer, 0, iByteSize);
                    iRunningByteTotal += iByteSize;
                    intProgress = Convert.ToUInt16(dProgressPercentage);
                    // Update the progress bar.
                    bgWorker.ReportProgress(intProgress);

                }                    
                // Close the output file.
                OutputFile.Close();
            }
            // Close the input file.
            InputFile.Close();
        }
    }

正如我所说,进度条正在更新,但是我收到错误,因为它似乎在文件达到100%后继续复制。如果我在bgWorker.ReportProgress(intProgress)行之后立即放入MessageBox.Show(Convert.ToString(intProgress)),对话框将弹出101文本。任何帮助将不胜感激。

3 个答案:

答案 0 :(得分:9)

您将运行总计除以块缓冲区的长度,而不是整个流,这意味着结果基本上是无限制的。你也没有乘以100,但这个问题被比率增长大于1的事实掩盖了。

但是你看起来非常困难 - 你想要的代码就是:

 bgWorker.ReportProgress((int)(100 * runningByteTotal / fileLength))

你应该在循环开始之前设置fileLength(它需要是文件的长度,而不是文件名,正如@azyberezovsky在他的回答中指出的那样)。

您可以使用简单的整数运算来进行此计算,而不是需要浮点类型,只要在除法之前乘以100即可。

作为一个风格点,你不需要在变量名前面的所有'我和's' - 这不被认为是好的C#风格。变量通常也不是以大写字母开头的 - 如果没有别的话,那就会混淆SO代码语法高亮显示......

答案 1 :(得分:1)

这不是文件大小 - 它只是文件名字符串的长度:

Int64 iSize = strInputFile.Length;

这也不是文件大小,这是用于将数据写入输出文件的缓冲区大小:

dTotal = (double)byteBuffer.Length;

您需要的是

private void bgWorker_DoWork(object sender, DoWorkEventArgs e)
{
    using (FileStream inputFile = new FileStream(strInputFile, FileMode.Open, FileAccess.Read, FileShare.None))
    using (FileStream outputFile = new FileStream(strOutputFile, FileMode.Create, FileAccess.Write, FileShare.None))
    {
        long totalBytesToWrite = inputFile.Length;
        long totalBytesWritten = 0;       
        byte[] buffer = new byte[512]; // provide any buffer size here
        int bytesToWrite;
        ushort percentage;

        while ((bytesToWrite = inputFile.Read(buffer, 0, buffer.Length)) > 0)
        {
            outputFile.Write(buffer, 0, bytesToWrite);
            totalBytesWritten += bytesToWrite;
            percentage = (ushort)((100 * totalBytesWritten)/totalBytesToWrite);
            bgWorker.ReportProgress(percentage);
        }
    }
}

请记住 - 如果您使用using块,则无需手动关闭流 - 此块将在此块的末尾处理(即关闭)。

答案 2 :(得分:0)

声明最大值:

pbCopyProgress.Maximum = InputFile.Read(byteBuffer, 0, byteBuffer.Length)

删除行:

percentage = (ushort)((100 * totalBytesWritten)/totalBytesToWrite);

来自bgWorker_DoWork,并在bgWorker_DoWork中循环之前声明计数器。例如:

int counter = 1;

在关闭括号之前递增计数器(counter++); 在bgWorker_ProgressChanged中更新百分比:

pbCopyProgress.Value = e.ProgressPercentage;

如果您想填写任何带有文字的标签,显示下一行计算百分比的百分比:

int percent = 100 / (byteBuffer.Length / e.ProgressPercentage);
Label1.Text = String.Format("Passed: {0} %, percent.ToString());

这些行也应该在bgWorker_ProgressChanged