【问题标题】:The process cannot access the file because it is being used by another process at deletion该进程无法访问该文件,因为它正在被另一个进程在删除时使用
【发布时间】:2012-06-01 15:56:12
【问题描述】:

我以为我通过关闭和处置我的阅读器解决了这个问题,但在某些情况下该文件仍在使用中。接下来我调用了垃圾收集器,因此文件将被释放。 这解决了 99% 的所有会导致此错误的问题。 使用的代码:

        public override void Finish()
        {
            // Kill the reader!
            if (_reader != null)
            {
                _reader.Close();
                _reader.Dispose();

                // Make sure the server doesn't hold the file
                GC.Collect();
            }
            DeleteFile();
        }

Finish 在处理文件内容的大进程之后调用。

当我处理一个只有 1 行(或很少)行的文件时,我有时会收到此错误。似乎 windows 很快,DeleteFile(); 失败了。 我很难重现此错误,但有时它会连续发生两次。
当我处理需要超过 2 秒的文件时,这种情况永远不会发生。
我不能使用 using ,因为文件可以是 GB 的,并且 Windows 不喜欢它的内存太满时。此外,这种方式的过程执行得更好。

问题:
我还能做些什么来防止这个错误吗?

PS:请随时询问更多信息。

编辑:
删除文件的代码

        protected void DeleteFile()
        {
            // Delete the file
            if (FileName != null && File.Exists(FileName))
                File.Delete(FileName);
        }

创建文件的代码

        protected void WriteFile()
        {
            // Prepare variables
            string path = Path.GetTempPath();

            path += "\\MyTempFile";

            // Modifiy path to avoid overwriting an existing file.

            path += ".csv";

            // Write the file to the temp folder
            using (FileStream fs = new FileStream(path, FileMode.Create))
            {
                fs.Write(MyFile, 0, MyFile.Length);
            }

            // Was the writing successfully completed?
            _FileName = File.Exists(path) ? path : null;
        }

创建阅读器的代码

        protected override void ReadFile()
        {
            if (FileName == null)
                WriteFile();

            // Read the lines
            _reader = new StreamReader(FileName, Encoding.Default, true);
            while (_reader.Peek() != -1)
            {
                TotalRows++;
                _reader.ReadLine();
            }

            // Read the lines
            _reader = new StreamReader(FileName, Encoding.Default, true);
        }

我使用一个抽象类来确定应该如何读取输入。 使用以下语句,我将遍历文件的内容。

 while (FileReader.NextRow(out currentRow, out currentRowNumber))
        {
               // Process current Row...
        }

NextRow() 方法长这样

        public override bool NextRow(out List<object> nextRow, out int rowNumber)
        {
            if (RowNumber > TotalRows)
            {
                nextRow = null;
                rowNumber = 0;

                return false;
            }

            // Set the row number to return
            rowNumber = RowNumber;

            // Prepare the row
            nextRow = _reader.ReadLine().ExtensionThatProcessesTheRow();
            RowNumber++;

            return true;
        }

while 循环结束后,我调用完成过程。 FileReader.Finish();

【问题讨论】:

  • 您不需要调用 GC.Collect。您不应该这样做,而且它应该不会影响删除文件的能力。
  • 访问文件的代码是什么样的?如果我们能看到它,我们可以在那里提出更好的建议。
  • 我们需要查看您用于创建、与之交互、删除这些文件的所有代码。您可能在某处泄漏了一个对象,或者两个线程同时与同一个文件进行交互。
  • @ChrisShain 如果我泄漏了一个对象,我认为错误应该是随之而来的。病毒扫描程序/索引器/任何持有文件被锁定以供删除的东西是不是有可能?
  • @Joe 你能解释一下为什么我不应该打电话给 GC.Collect 吗?

标签: c# file-in-use


【解决方案1】:

正如你所说的那样,它有时只会发生,它可能只是被锁住了,如果你做了一个检查,那么希望如果它在你开始对它进行另一次检查时失败了,那么它应该有摆脱缓存锁的时间。 如果您使用这样的方法来检查文件是否仍在使用中:

public bool CheckIfFileIsBeingUsed(string fileName){

     try{    
         File.Open(fileName, FileMode.Open, FileAccess.Read, FileShare.None);
          }

      catch (Exception exp){
               return true;
        }

      return false;

}

如果返回 false 则继续删除文件,否则等待然后再次运行检查。

【讨论】:

  • 这可能意味着我陷入了循环并且不安全。 While(FileIsInUse) { Thread.Sleep(100)}
  • 你总是可以让它进入一个 do while 循环,并添加一个计数器,在多次尝试后打破循环并发布一个用户友好的错误,说明文件已被锁定。
  • 嗯。我会试一试,谢谢你的提示。我会回到这个。
【解决方案2】:

注意:这应该是注释,但我需要额外的空间。

这段代码没有意义:

// Prepare variables
string path = Path.GetTempPath();

// Write the file to the temp folder
using (FileStream fs = new FileStream(path, FileMode.Create))

Path 是临时文件的目录。您应该无法创建具有该名称的文件。

此外,这里使用了一个名为 FileName 的变量:

protected void DeleteFile()
{
    // Delete the file
    if (FileName != null && File.Exists(FileName))
        File.Delete(FileName);
}

但在 WriteFile 中,您使用的是一个名为 _FileName 的变量:

// Was the writing successfully completed?
_FileName = File.Exists(path) ? path : null;

基于上述情况,我的猜测是,你没有写你认为你正在写的东西,或者没有删除你认为你正在删除的东西。

【讨论】:

  • 相信我这行得通:P...正如我所说,我使用抽象类。 _FileName 是私有属性,而 FileName 是公共属性。
  • 上面调用string path = Path.GetTempPath();后变量path的值是多少?文档明确指出“返回当前用户临时文件夹的路径”。 msdn.microsoft.com/en-us/library/…
  • 我编辑了我的问题。我看到我忘了复制一些代码行。我将其设为 .csv 并添加 (n) 以确保文件名是唯一的。
【解决方案3】:

我想我找到了问题...
ReadFile() 中重置此阅读器之前未处置此阅读器。

        _reader = new StreamReader(FileName, Encoding.Default, true);
        while (_reader.Peek() != -1)
        {
            TotalRows++;
            _reader.ReadLine();
        }

我改成了。

            using (var reader = new StreamReader(FileName, Encoding.Default, detectEncodingFromByteOrderMarks: true))
            {
                while (reader.Peek() != -1)
                {
                    TotalRows++;
                    reader.ReadLine();
                }
            }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-11-29
    • 1970-01-01
    • 1970-01-01
    • 2010-12-10
    相关资源
    最近更新 更多