2012-05-31 26 views
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(或很少)行我有时得到此错误。它似乎是快速和DeleteFile();失败的窗口。 我很难再现这个错误,但有时它只是连续发生两次。
当我处理文件需要多于2秒的时间来处理时,这绝不会发生。
我无法使用,因为文件可以是GB的,并且当内存变得太满时,Windows不喜欢它。此外,这种方式的过程表现更好。

问题:
有什么我可以做,以防止这个错误?注:请随时索取更多信息。

编辑:
代码删除文件

 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();

+5

您不需要调用GC.Collect。你不应该这样做,并且它不应该影响删除文件的能力。 – Joe

+2

访问文件的代码是什么样的?如果我们能看到它,我们可以在那里提出更好的建议。 – Josh

+2

我们需要查看您用于创建,与*进行交互以及*删除这些文件的所有代码。你有可能在某处泄漏了一个对象,或者两个线程正在同时与同一个文件进行交互。 –

回答

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(); 
       } 
      } 
1

正如你所说,它只是有时会发生,它可能只是锁持有,如果你做一个检查,然后希望如果它失败的时候,你轮到做另一个检查它,那么它应该有时间摆脱缓存的锁。 如果使用这样的方法来检查是否仍在使用的文件:

public bool CheckIfFileIsBeingUsed(string fileName){ 

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

     catch (Exception exp){ 
       return true; 
     } 

     return false; 

}

如果它返回false,那么继续和删除文件,其他明智的等待,然后运行再检查一遍。

+0

这可能意味着我卡在一个循环中,并不安全。 While(FileIsInUse){Thread.Sleep(100)} < - 可能使电脑等待很长时间。我确实考虑过这个;)。 – Mixxiphoid

+0

你总是可以把它变成一个do while循环,并添加一个计数器,在经过这么多次尝试之后打破循环,并发布用户友好的错误说明文件被锁定。 –

+0

嗯。我会试一试,谢谢你的提示。我会回到这个。 – Mixxiphoid

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; 

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

+0

相信我这个作品:P ...正如我所说我使用抽象类。 _FileName是FileName是公共属性的私有属性。 – Mixxiphoid

+0

调用'string path = Path.GetTempPath();'之后变量'path'的值是多少?该文档明确指出,“返回当前用户的临时文件夹的路径”。 http://msdn.microsoft.com/en-us/library/system.io.path.gettemppath.aspx –

+0

我编辑了我的问题。我看到我忘了复制一些代码行。我使它成为一个.csv并添加一个(n)以确保文件名是唯一的。 – Mixxiphoid

相关问题