簡體   English   中英

進程無法訪問文件,因為它被另一個進程使用

[英]c# - Process cannot access file because it is used by another process

在這種情況下,我有一個應用程序,每2秒會覆蓋xml文件。 然后,我有了這個C#應用程序,它每1-2秒讀取一次此文件。 這個過程運行良好,但是有時我會收到錯誤消息,

進程無法訪問文件,因為它被另一個進程使用

我正在使用xmldocument.load打開和讀取xml文件。

我該怎么做才能解決這個問題? 我嘗試在不同的計算機上運行,​​這絕對是隨機的,因為在我的計算機上,它在錯誤發生之前已經在其他計算機上運行了6個小時,

因為我的c#程序將繼續讀取該文件,除非用戶單擊一個按鈕以停止數據記錄過程

因為我希望程序只要用戶不停止就可以繼續運行。 請幫忙

請告訴您您是否嘗試使用FileStream變量讀取XmlDocument內容,該變量已使用特殊指定的構造函數通過適當的FileMode以及FileAccessFileShare參數實例化。 您可以使用Load方法的實現來加載 XmlDocument的內容,該方法將適當打開的文件流(用於共享寫入,反之亦然)以文件流為參數。

請嘗試使用以下代碼寫入文件:

XmlDocument xmlDocument = new XmlDocument();
using (FileStream fileStream = new FileStream("C:\\test.xml", FileMode.Append, FileAccess.Write, FileShare.Read))
{
    xmlDocument.Load(fileStream);
}

以及以下用於從文件讀取的代碼:

XmlDocument xmlDocument = new XmlDocument();
int attempts = 5;
Exception cannotReadException = null;
while (attempts > 0)
{
    try
    {
        using (FileStream fileStream = new FileStream("C:\\test.xml", FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
        {
            xmlDocument.Load(fileStream);
            attempts = 0;
        }
    }
    catch (Exception exception)
    {
        cannotReadException = exception;
        System.Threading.Thread.Sleep(100);
        attempts--;
    }
}

if (cannotReadException != null)
{
    throw cannotReadException;
}

當另一個應用程序寫入同一文件時,您將無法從文件中讀取文件,如果您同時開發了這兩個應用程序,我將推薦使用真正的數據庫而不是XML文件。 對於示例SQLite

但是,如果您不使用xml文件,則可以捕獲XmlDocument.Load引發的異常,然后嘗試再次讀取以希望其他過程已通過寫入完成

該文件有時仍被標記為操作系統正在使用,另一台計算機正在使用或病毒掃描程序正在使用,並且對於程序而言,釋放的速度不夠快。 您應該插入一個小的超時/延遲,或者使用try .. catch捕獲異常,然后在短暫的延遲后再次嘗試。

使用計時器時,在處理文件時應停止計時器,直到完成:

private void timer_Tick(object sender, EventArgs e)
{
  try
  {
    timer.Stop();
    //read write whatever ...
  }
  catch(){}  
  timer.start(); 
}

為了避免沖突,請按照以下步驟進行覆蓋:

  • 將新XML寫入與舊XML相同位置的臨時文件中
  • 將新文件重命名為舊文件

在UNIX文件系統上,這將避免在寫入過程中讀取嘗試失敗的問題。 不確定Windows,但應該可以。

為了擴展其他人的建議,下面是一個示例,說明如何使用try catch塊解決沖突:

private XmlDocument OpenXML(string filename, int retryCount = 0)
{
    XmlDocument retval = new XmlDocument();

    try
    {
        retval.Load(filename);
    }
    catch
    {
        if (retryCount < 5)
        {
            retval = OpenXML(filename, retryCount + 1);
        }
        else
        {
            return null;
        }
    }

    return retval;
}

如果需要,您可以在捕獲中添加一個暫停,或者在達到最大嘗試次數后增加重試次數/以不同的方式進行處理。

正如已經建議的那樣,您可以實現一種簡單的x毫秒等待時間,然后重試。

如果您使用的是Windows,並且可以訪問這兩個程序的源代碼,則可以使用本機Win32函數來創建信號量,以調節對文件的訪問。 有關更多詳細信息,請參見此頁面。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM