2013-02-22 185 views
2

我有一個進程A讀入一些其他進程B產生的一些數據。數據通過文件系統「交換」。爲了確保該文件存在,處理當前檢查類似這樣的文件的存在:一個進程通過文件系統等待另一個進程的輸出

while (!File.Exists(FileLocation)) 
{ 
    Thread.Sleep(100); 
} 

這似乎只工作的99%的時間。另外1%的時間,過程A確定該文件存在,但過程B尚未寫入所有內容(即某些數據缺失)。

是否有另一種更簡單的方法可以讓上述情況更符合防彈要求?謝謝。

+0

雖然您應該使用FileSystemWatcher(http://msdn.microsoft.com/en-us/library/system.io.filesystemwatcher.aspx),但並不能解決您的問題,您的投票。你必須等到文件沒有改變大小(在這裏插入適當的秒數)。哈克哈克。 – 2013-02-22 13:13:59

+0

你看過FileSystemWatcher了嗎? http://msdn.microsoft.com/en-us/library/system.io.filesystemwatcher.aspx – Christian 2013-02-22 13:15:07

+0

謝謝我正在研究FileSystemWatcher,但我不認爲它適用於我的情況。 – cs0815 2013-02-22 13:15:12

回答

3

是否有另一個更簡單的方法來使上述情況更符合防彈要求?

您可以使用Mutex進行可靠的進程間同步。另一種可能性是使用FileSystemWatcher

3

確定該文件存在之後,可以嘗試打開該文件進行獨佔訪問,如果另一個進程仍有打開該文件將失敗:

try 
{ 
    File.Open("foo",FileMode.Open,FileAccess.Read,FileShare.None); 
} 
catch(IOException ex) 
{ 
    // go back to 
} 
+0

看起來很有趣。是不是有點狡猾... – cs0815 2013-02-22 13:28:16

+0

是的,這是解決方案。每次失敗時,請稍等片刻,然後再試一次。最後另一個進程將關閉文件,這將成功,你很好去。它是狡猾的,但除非你可以改變另一個過程來使用正確的信號,否則這是你可能做的最好的。 – 2013-02-22 13:29:05

+0

當然這並不理想,但如果你不控制「製片人」那一方,我不確定你有多少選擇。如果你確實控制了生產者端,你可以生成第二個文件(「foo.lock」),一旦寫入完成就會消失,並且你可以檢查兩者。 – jlew 2013-02-22 13:34:21

0

嘗試FileSystemWatcher

當 目錄或目錄中的文件發生更改時,將監聽文件系統更改通知並引發事件。

+0

它不適用於我的情況,因爲當我停止順序執行以等待文件被完全寫入時,我無法捕捉事件......除非我錯過了某些內容。 – cs0815 2013-02-22 13:36:33

1

鑑於您認爲您可以更改這兩個進程的代碼,您可以使用EventWaitHandle在進程之間進行通信。

在您創建文件的程序中,在Main()方法中,您可以創建一個EventWaitHandle並將其保留,直到程序結束。您需要在程序中傳遞EventWaitHandle對象,以便它可用於創建文件的代碼位(或提供文件創建代碼可以調用的某些方法來設置事件)。

using (EventWaitHandle readySignaller = new EventWaitHandle(false, EventResetMode.ManualReset, "MySignalName")) 
{ 
    // Rest of program goes here... 
    // When your program creates the file, do this: 

    readySignaller.Set(); 
} 

然後讓在在等待該文件的程序像這樣的代碼:

// Returns true if the wait was successful. 
// Once this has returned true, it will return false until the file is created again. 

public static bool WaitForFileToBeCreated(int timeoutMilliseconds) // Pass Timeout.Infinite to wait infinitely. 
{ 
    using (EventWaitHandle readySignaller = new EventWaitHandle(false, EventResetMode.ManualReset, "MySignalName")) 
    { 
     bool result = readySignaller.WaitOne(timeoutMilliseconds); 

     if (result) 
     { 
      readySignaller.Reset(); 
     } 

     return result; 
    } 
} 

注意:如果我們成功地等待注意,我復位信號,同時保持復位狀態,直到其他過程再次設置它。如果您需要,您可以以不同的方式處理邏輯;這只是一個例子。

基本上我們在這裏(邏輯上)在這裏做的是在兩個進程之間共享一個bool。你必須小心你設置和重置共享布爾的順序。

相關問題