简体   繁体   English

删除/创建文件会在经过大量迭代后抛出System.UnauthorizedAccessException

[英]Deleting/creating files throws System.UnauthorizedAccessException after a lot of iterations

While testing some things out about writing/creating/deleting of files i made the following program that deletes and creates a file in a loop n times. 在测试有关写入/创建/删除文件的一些事情时,我制作了以下程序,它在循环中删除并创建一个文件n次。

static string path = @"C:\Users\Remy\Desktop\Testing";
static readonly int sampleSize = 10000; // Amount of iterations the methods will be run for.

static byte[] sourceFile;

static void Main(string[] args)
{
    using (FileStream fs = new FileStream(path + @"\SourceFile.txt", FileMode.Open, FileAccess.Read))
    {
        sourceFile = new byte[fs.Length];
        fs.Read(sourceFile, 0, sourceFile.Length);
    }

    string filePath = path + @"\Destination.txt";
    for (int i = 0; i < sampleSize; i++)
    {
        if (File.Exists(filePath))
        {
            File.SetAttributes(filePath, FileAttributes.Normal);
            File.Delete(filePath);//Error sometimes throws here.
        }

        using (FileStream file = File.OpenWrite(filePath))
        {
            file.Write(sourceFile, 0, sourceFile.Length);
        }
    }

    Console.ReadLine();
}

This program works most of the time as expected when the amount of iterations isn't too high (about 1000). 当迭代量不是太高(大约1000)时,该程序大多数时间按预期工作。 It will delete the old file and create a new one. 它将删除旧文件并创建一个新文件。

However when I increase the amount of iterations to 10000/100000 issues arise where on rare occassion (about 0.03% of the times) it throws System.UnauthorizedAccessException at using (FileStream file = File.OpenWrite(filePath)) , while succesfully passing the other 99.97% of the time. 然而,当我将迭代量增加到10000/100000时会出现罕见的问题(大约0.03%的时间),它会在using (FileStream file = File.OpenWrite(filePath))时抛出System.UnauthorizedAccessException using (FileStream file = File.OpenWrite(filePath)) ,同时成功传递另一个99.97%的时间。 When the error throws the file doens't get created. 当错误抛出文件时,不会创建。

This happens both in VS (as admin) using Debug/release, and on the build .exe run as administrator. 在使用Debug / release的VS(作为管理员)和作为管理员运行的build .exe上都会发生这种情况。

When looking around this issue i found the following answers regarding Unauth... exceptions. 在查看此问题时,我发现以下关于Unauth...例外的答案。

  • this answer suggests setting the Attributes, but as seen in my example I already do that. 这个答案建议设置属性,但正如我的例子中所见,我已经这样做了。
  • this and some other answers suggest running the application with admin rights. 这个和其他一些答案建议使用管理员权限运行应用程序。 Which i'm already doing aswel. 我已经在做什么了。

I also added the permissions of the parent folder to allow full control to Everyone on all files and subfolders. 我还添加了父文件夹的权限,以允许对所有文件和子文件夹上的Everyone进行full control

At first I thought maybe the file I was creating wasn't big enough (currently writing 976kb of random data) and for some reason the program iterated over creation/deletion faster than the OS/harddisk could handle. 起初我想也许我正在创建的文件不够大(目前正在编写976kb的随机数据),并且由于某种原因,程序迭代创建/删除比OS /硬盘可以处理的更快。 But the same behaviour occurs when increasing filesize 但是增加文件大小时会出现相同的行为

I've tested it across 3 machines, and it happened on them all. 我已经在3台机器上测试了它,它发生在它们上面。

Can this be a case of windows throwing an exception because of a false positive? 这可能是由于误报导致Windows抛出异常的情况吗? Seeing that it only happens on big itterations? 看到它只发生在大的itterations上? Am I missing something completely different here? 我错过了一些完全不同的东西吗?

Note: I'm not looking for a way to handle the the exception. 注意:我不是在寻找处理异常的方法。 I can handle that. 我能解决这个问题。 What I'm looking for a reason why this odd behaviour happens, and if possible to prevent it instead of curing it 我正在寻找一个理由,为什么这种奇怪的行为发生,如果可能的话,以防止它,而不是固化


Environment 环境

Disk i'm writing to is a Crucial MX300 SSD, using sata 3 without a RAID. 我写的磁盘是Crucial MX300 SSD,使用没有RAID的sata 3。 16 GB ram. 16 GB内存。 OS Windows 10 (pro) 64-bit. OS Windows 10(专业版)64位。 The system is running as idle as possible while running the program. 运行程序时,系统尽可能空闲运行。

The Console application is targeting .NET Framework 4.6.1 build using Visual studio 2017 with Release Any CPU setting. 控制台应用程序的目标是使用Visual Studio 2017和Release Any CPU设置构建.NET Framework 4.6.1。


Additional things i've tried as per comment suggestions: 我根据评论建议尝试的其他事项:

I tried adding a Thread.Sleep after creation and deletion to make sure Windows gets to clear the file cache. 我尝试在创建和删除后添加Thread.Sleep以确保Windows能够清除文件缓存。 This still throws the exception but this time it throws the exception on File.Delete(filePath); 这仍然会引发异常,但这次它会在File.Delete(filePath);上抛出异常File.Delete(filePath); instead. 代替。

Turning off Windows Defender etc also yields the result of the error being thrown on File.Delete(filePath) instead of using(FIleStream....) aswel. 关闭Windows Defender等也会产生在File.Delete(filePath)上抛出错误的结果,而不是using(FIleStream....) aswel。

Write to file using the following instead: 使用以下代码写入文件:

using (FileStream file = new FileStream(filePath, FileMode.Open, FileAccess.Write, FileShare.None)) 
{ 
    file.Write(sourceFile, 0, sourceFile.Length); file.Flush(flushToDisk: true); 
}

also yields the same Exception being thrown 也会产生相同的异常抛出

There is no way you can get rid of this kind of issues, only way to handle is to prevent or avoid and make some logs if operation fails. 你无法摆脱这种问题,只有处理的方法是在操作失败时防止或避免并制作一些日志。 Try operation like this multiple times if fails. 如果失败,请多次尝试这样的操作。 Previously I have created one, here is code snippet. 以前我创建了一个,这里是代码片段。

public IList<string> ReadLineByLineFromFile( string filePath )
{
    const int numberOfRetries = 3;
    const int delayOnRetry = 500;

    bool success = false;
    List<string> logs = null;

    for ( int i = 0; i <= numberOfRetries && success == false; i++ )
    {
        try
        {
            logs = new List<string>();

            const Int32 bufferSize = 128;
            using ( var fileStream = File.Open( filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite ) )
            using ( var streamReader = new StreamReader( fileStream, Encoding.UTF8, true, bufferSize ) )
            {
                string line;

                while ( ( line = streamReader.ReadLine() ) != null )
                {
                    logs.Add( line );
                }
            }

            success = true;
        }
        catch ( IOException ex ) when ( i < numberOfRetries )
        {
            Local.Instance().Logger.Warn( ex, "Retrying reading logs from file path {0}, retry count {1} with dealy {2} ms.", filePath, i + 1,
                delayOnRetry );

            System.Threading.Thread.Sleep( delayOnRetry );
        }
    }

    GC.Collect();

    return logs;
}

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

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