2012-05-31 60 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

相關問題