c# - .NET 文件访问冲突

标签 c# .net

我觉得发布这个有点愚蠢,但这似乎是一个真正的问题,我已经足够简单以证明它不应该失败。作为我工作的一部分,我负责维护将文件置于版本控制之下并将它们复制到其他位置的构建系统。听起来很简单,但在尝试复制我应该已设置为“正常”的文件时,我经常遇到文件访问冲突。

下面的代码示例只是创建一组测试文件,将它们设为只读,然后将它们复制到另一个文件夹。如果目标文件夹中已经存在文件,则清除RO属性,这样文件复制不会失败。

代码在一定程度上起作用,但在看似随机的点上,尝试复制文件时会抛出异常。代码都是单线程的,所以除非 .NET 在幕后做了一些导致属性设置延迟的事情,否则我无法真正解释这个问题。

如果有人能解释为什么会这样,我会很感兴趣。除非我肯定做错了什么,否则我不会寻找解决方案,因为我已经处理了这个问题,我只是好奇,因为似乎没有其他人报告过与此相关的任何事情。

经过几次迭代后,我得到如下内容:

“System.UnauthorizedAccessException”类型的第一次机会异常发生在 mscorlib.dll 中 附加信息:拒绝访问路径“C:\TempFolderB\TEMPFILENAME8903.txt”。

另一个事实,如果您在文件复制之前获取文件属性,结果状态表明文件属性确实正常,但对本地文件的检查显示它为只读。

    /// <summary>
    /// Test copying multiple files from one folder to another while resetting RO attr
    /// </summary>
    static void MultiFileCopyTest()
    {
        /// Temp folders for our test files
        string folderA = @"C:\TempFolderA";
        string folderB = @"C:\TempFolderB";

        /// Number of files to create
        const int fileCount = 10000;

        /// If the test folders do not exist populate them with some test files
        if (System.IO.Directory.Exists(folderA) == false)
        {
            const int bufferSize = 32768;

            System.IO.Directory.CreateDirectory(folderA);
            System.IO.Directory.CreateDirectory(folderB);

            byte[] tempBuffer = new byte[bufferSize];

            /// Create a bunch of files and make them all Read Only
            for (int i = 0; i < fileCount; i++)
            {
                string filename = folderA + "\\" + "TEMPFILENAME" + i.ToString() + ".txt";

                if (System.IO.File.Exists(filename) == false)
                {
                    System.IO.FileStream str = System.IO.File.Create(filename);
                    str.Write(tempBuffer, 0, bufferSize);
                    str.Close();
                }

                /// Ensure files are Read Only
                System.IO.File.SetAttributes(filename, System.IO.FileAttributes.ReadOnly);
            }
        }

        /// Number of iterations around the folders
        const int maxIterations = 100;

        for (int idx = 0; idx < maxIterations; idx++)
        {
            Console.WriteLine("Iteration {0}", idx);

            /// Loop for copying all files after resetting the RO attribute
            for (int i = 0; i < fileCount; i++)
            {
                string filenameA = folderA + "\\" + "TEMPFILENAME" + i.ToString() + ".txt";
                string filenameB = folderB + "\\" + "TEMPFILENAME" + i.ToString() + ".txt";

                try
                {

                    if (System.IO.File.Exists(filenameB) == true)
                    {
                        System.IO.File.SetAttributes(filenameB, System.IO.FileAttributes.Normal);
                    }

                    System.IO.File.Copy(filenameA, filenameB, true);
                }
                catch (System.UnauthorizedAccessException ex)
                {
                    Console.WriteLine(ex.Message);
                }
            }
        }
    }

最佳答案

(这不是一个完整的答案,但我还没有足够的声誉来发表评论......)

我不认为你做错了什么,当我运行你的测试代码时,我每次都能重现问题。我从来没有在没有发生错误的情况下超过 10 次迭代。

我做了进一步的测试,这可能会阐明这个问题:

我将 TempFolderA 中的所有文件设置为隐藏。

然后我确保 TempFolderB 中的所有文件都没有被隐藏。

我在 Console.WriteLine(ex.Message) 上设置了一个断点

我运行了代码,如果它通过了第 1 次迭代,那么我就停止,重置隐藏属性并再次运行。

尝试几次后,我在第一次迭代中失败了,所以我在 TempFolderB 上打开 Windows 资源管理器并向下滚动到有问题的文件。

文件大小为 0 字节,但设置了 RHA 属性。

不幸的是,我不知道这是为什么。 Process Monitor 不显示任何其他可能相关的事件。

关于c# - .NET 文件访问冲突,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24915478/

相关文章:

c# - 包含集合的自定义配置部分

c# - 递归如何打印列表的总和

.net - C++ 编译器是否可以跨 DLL 内联方法调用?

c# - 使用数据注释进行验证不起作用

C#:WCF:接口(interface)继承和转换问题

c# - 为什么 IE9+ 上的网络浏览器不支持 document.createEvent 以及如何修复它?

c# - 字符串只包含一组给定的字符

c# - 安全运行时引擎 VS AntiXSS 库

.net - 如何在 WPF ListView 被数据绑定(bind)时显示 Progress Spinner(或其他 UI)?

c# - 如何创建一个可序列化的类,其中包含一组类中的一个类的实例