C# 尝试使用ReadAsync报告读取文件的进度时ArgumentOutOfRange异常

C# 尝试使用ReadAsync报告读取文件的进度时ArgumentOutOfRange异常,c#,asynchronous,progress-bar,C#,Asynchronous,Progress Bar,我正在尝试读取文件并使用进度条显示更新。我在读取文件的最后一部分时不断遇到此错误: System.ArgumentOutOfRangeException:'7340032'的值对'Value'无效“值”应介于“最小值”和“最大值”之间。 参数名称:值' 在这个地方 progressBar.Value = position; 这是我的全部密码 private async void readFileWithProgressBar( string fil

我正在尝试读取文件并使用进度条显示更新。我在读取文件的最后一部分时不断遇到此错误:

System.ArgumentOutOfRangeException:'7340032'的值对'Value'无效“值”应介于“最小值”和“最大值”之间。 参数名称:值'

在这个地方

progressBar.Value = position;
这是我的全部密码


        private async void readFileWithProgressBar(
              string fileToRead, ProgressBar progressBar)
        {
            var fileSize = (int)(new FileInfo(fileToRead).Length);

            // Set the maximum value of the progress bar to the file size
            progressBar.Maximum = fileSize;

            // Now read the file with FileStream functions
            int position = 0;
            int blockSize = 1024 * 1024; // Read 1 megabyte at a time
            byte[] allData = new byte[fileSize]; 

            using (var fs = new FileStream(fileToRead, FileMode.Open))
            {
                var bytesLeft = fileSize;
                while (bytesLeft > 0)
                {
                    await fs.ReadAsync(
                         allData, position, Math.Min((int)bytesLeft, blockSize));

                    // Advance the read position
                    position += blockSize;

                    // Update the progress bar
                    progressBar.Value = position; //ERROR IS HERE

                    bytesLeft -= blockSize;
                }
            }
        }
private void按钮2\u单击(对象发送者,事件参数e)
{
readFileWithProgressBar(@“\test.txt”,progressBar1);
}

我的代码几乎执行到最后,但突然停止并给出上面的错误。

问题是您使用的是
块大小,而不是读取的字节数。假设您有一个15字节的文件,并且您的
blockSize
设置为
10

迭代将按如下方式进行:

int bytesRead = await fs.ReadAsync(allData, position, Math.Min((int)bytesLeft, blockSize));

// Advance the read position
position += bytesRead;
progressBar.Value = position;
  • 将最大值设置为15,将位置设置为0
  • 从文件中读取最多10个字节
  • 将10添加到位置(新值:10)
  • 设置进度=10
  • 从文件中读取最多10个字节。我们只剩下5个字节要读,所以我们实际上只剩下5个字节
  • 将10添加到位置(新值:20)
  • 设置进度=20
  • 如您所见,新的进度值(20)大于最大值(15)

    幸运的是,
    await ReadAsync
    为您提供了读取的字节数,因此您可以将其存储并应用于位置。将代码更改为如下所示:

    int bytesRead = await fs.ReadAsync(allData, position, Math.Min((int)bytesLeft, blockSize));
    
    // Advance the read position
    position += bytesRead;
    progressBar.Value = position;
    

    除了在文件末尾出现这种情况外,由于其他原因,一些
    实现读取的字节数可能比预期的要少。有时,注意实际读取的字节数很重要,而不是请求读取的字节数。

    等待ReadAsync
    返回一个整数,指示读取的字节数。如果盲目假设每次读取都会填充缓冲区/按缓冲区大小提前位置,则可能会导致文件损坏。正如John所指出的,capture of bytes ReadAsync返回它读取的字节数,并根据该字节数(而不是整个缓冲区)前进/工作。您也不需要记录剩余的字节数;只需读取,直到不再有字节读取;使用较小的缓冲区可能会获得更好的性能(通常选择低于16kb的缓冲区)