该进程无法访问该文件,因为它在删除时正被另一个进程使用

本文关键字:进程 另一个 删除 访问 文件 因为 | 更新日期: 2023-09-27 18:35:49

我以为我通过关闭和处置我的阅读器解决了这个问题,但在某些情况下文件仍在使用中。接下来,我调用了垃圾收集器,因此将释放该文件。这解决了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();
        }

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

当我处理只有 1 行(或很少)行的文件时,有时会收到此错误。似乎窗口正在快速,DeleteFile();失败。我很难重现此错误,但有时它只是连续发生两次。
当我处理处理文件需要超过 2 秒的时间时,这永远不会发生。
我不能使用,因为文件可以是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();

该进程无法访问该文件,因为它在删除时正被另一个进程使用

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

public bool CheckIfFileIsBeingUsed(string fileName){
     try{    
         File.Open(fileName, FileMode.Open, FileAccess.Read, FileShare.None);
          }
      catch (Exception exp){
               return true;
        }
      return false;

}

如果它返回 false,则继续删除该文件,其他明智的等待,然后再次运行检查。

注意:这可能应该是一个评论,但我需要额外的空间。

此代码没有意义:

// Prepare variables
string path = Path.GetTempPath();
// Write the file to the temp folder
using (FileStream fs = new FileStream(path, FileMode.Create))

路径是临时文件的目录。 您不应该能够创建具有该名称的文件。

此外,这里使用一个名为 文件名 的变量:

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;

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

我想我发现了问题...
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();
                }
            }