2011-10-24 132 views
10

如果文件不存在,我只想創建文件。
像A碼:僅在不存在的情況下創建文件

if (!File.Exists(fileName)) 
{ 
    fileStream fs = File.Create(fileName); 
} 

使其開啓的情況下,該文件將在「如果」到「創造」之間創建一個競爭條件。

我該如何避免它?

編輯:不能在這裏使用,因爲它是一個不同的進程(同一個應用程序的多個實例)
鎖。

+0

使用try {} catch {}? – ojlovecd

+0

同樣的應用程序?互斥體? –

回答

9

Kristian Fenn的答案几乎是我所需要的,只是使用不同的FileMode。這是我正在尋找的:

FileStream fs = new FileStream(fileName, FileMode.CreateNew); 
1

如果爭用的創建文件的嘗試處於相同的過程中,則可以在代碼周圍使用lock語句來防止爭用。

如果不是,則在調用File.Create時可能偶爾會發生異常。只要適當處理這個例外。即使在文件確實存在時處理異常,因爲拋出的異常相對昂貴,在創建之前檢查文件是否存在也是可取的。只有在競賽條件較低的情況下,這纔不可取。

+1

我希望你不要寫我使用的任何軟件。請確保以上猜測的安全。 – reinierpost

19

您還可以使用

FileStream fs = new FileStream(fileName, FileMode.OpenOrCreate); 

但是,你應該看看螺紋鎖固彷彿多個線程試圖訪問你可能會得到一個異常文件。

+0

MSDN並未說明該構造函數是否是線程安全的,因此您在多線程環境中提醒注意是正確的。 –

+1

兩個線程同時嘗試它將得到與['CreateFile'](http://msdn.microsoft.com/en-us/library/aa363858(VS.85).aspx)(作爲'FileStream'')相同的結果它的構造函數是Win32的一個包裝)同時被調用 - 一個線程將獲勝。據我瞭解,在內核級別,這是一個單一的操作:一個線程不會創建,而另一個線程不會打開。 – Richard

+0

謝謝理查德,很高興知道。 –

1

首先您鎖定或Monitor.Enter或TryEnter API來鎖定代碼的一部分。 其次,您可以使用FileStream API和FileMode.OpenOrCreate API。如果文件存在,它只是使用它,否則它只是創建它。

3

這是不是一個更好的解決方案。另請注意using(var stream...)使用它關閉流以避免IO異常。

if (!File.Exists(filePath)) 
{ 
    using (var stream = File.Create(filePath)) { } 
} 
相關問題