繁体   English   中英

C#文件流在写/读操作完成之前不会阻塞

[英]C# Filestream not blocking until write/read operation complete

我正在尝试编写一个将文件从一个位置复制到另一个位置并报告进度的类。 我遇到的问题是,当应用程序运行时,进度会立即从0飙升到100%,但是文件仍在后台复制。

    public void Copy(string sourceFile, string destinationFile)
    {
        _stopWatch.Start();

        _sourceStream = new FileStream(srcName, FileMode.Open);
        _destinationStream = new FileStream(destName, FileMode.CreateNew);

        read();
        //On a 500mb file, execution will reach here in about a second.
    }

    private void read()
    {
        int i = _sourceStream.Read(_buffer, 0, bufferSize);

        _completedBytes += i;

        if (i != 0)
        {
            _destinationStream.Write(_buffer, 0, i);

            TriggerProgressUpdate();

            read();
        }
    }

    private void TriggerProgressUpdate()
    {
        if (OnCopyProgress != null)
        {
            CopyProgressEventArgs arg = new CopyProgressEventArgs();
            arg.CompleteBytes = _completedBytes;

            if (_totalBytes == 0)
                _totalBytes = new FileInfo(srcName).Length;

            arg.TotalBytes = _totalBytes;

            OnCopyProgress(this, arg);
        }
    }

似乎正在发生的事情是FileStream仅在OS中排队操作,而不是阻塞直到读取或写入完成。

有什么方法可以禁用此功能而不会造成巨大的性能损失?

PS。 我正在使用测试源和目标变量,这就是为什么它们不匹配参数的原因。

谢谢克雷格

我不认为它可以使读取操作排队...毕竟,您有一个字节数组,在Read调用后它将有一些数据-数据最好是正确的。 可能只有正在缓冲的操作。

您可以尝试定期在输出流上调用Flush ...我不知道Flush在各种缓存级别上会走多远,但它可能要等到实际写入数据之后才能进行。 编辑:如果您知道这是FileStream ,则可以调用Flush(true) ,它将等待直到数据实际写入磁盘为止。

请注意,您不应经常执行此操作,否则性能会受到严重影响。 您需要在进度准确性的粒度与性能损失之间取得平衡,以进行更多控制,而不是让操作系统优化磁盘访问。

我担心您在这里使用递归-在非常大的文件上,您可能会毫无理由地感到栈溢出。 (CLR有时可以优化尾递归方法,但并非总是如此)。 我建议您改用循环。 国际海事组织,这也将更具可读性:

public void Copy()
{
    int bytesRead;
    while ((bytesRead = _sourceStream.Read(_buffer, 0, _buffer.Length)) > 0)
    {
        _destinationStream.Write(_buffer, 0, bytesRead);
        _completedBytes += bytesRead;
        TriggerProgressUpdate();
        if (someAppropriateCondition)
        {
            _destinationStream.Flush();
        }
    }
}

希望您顺便处理一下流。 我个人尽量避免使用可抛弃的成员变量。 有什么原因不能只在using语句中使用局部变量?

经过调查,我发现在FileStream的构造函数中使用“ FileOptions.WriteThrough”将禁用写缓存。 这会导致我的进度报告正确。 但是,它确实会降低性能,副本在Windows中花费13秒,在我的应用程序中花费20秒。 我将尝试优化代码并调整缓冲区大小,以查看是否可以加快速度。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM