1

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

4

3 回答 3

1

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

public bool CheckIfFileIsBeingUsed(string fileName){

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

      catch (Exception exp){
               return true;
        }

      return false;

}

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

于 2012-05-31T14:03:43.810 回答
0

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

这段代码没有意义:

// 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;

基于以上所述,我的猜测是,您并没有写出您认为正在写的内容,或者没有删除您认为正在删除的内容。

于 2012-05-31T16:27:17.317 回答
0

我想我发现了问题...
在将其重置为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();
                }
            }
于 2012-06-01T07:56:12.220 回答