2013-05-28 57 views
0

我有一個多線程應用程序。我的問題是,有時我得到一個錯誤,就像程序無法訪問一個文件,因爲它已被別的東西(應用程序的其他部分)使用。最佳解決方案解決文件無法訪問錯誤

現在我所做的就是捕捉異常並在100ms延遲後重復執行任務。

它正在工作,因爲應用程序不會經常打開這些文件,它只是在短時間內打開這些文件。

儘管我不滿意該解決方案,因爲它很醜,而且仍然可能出錯。

有沒有什麼好的方法來解決這個問題?如果沒有簡單的答案,並且您需要有關應用程序的更多信息(哪些文件,爲什麼我可以在同一時間訪問),我可以回答,我只是試圖保持簡單和通用的問題。

問候 丹尼爾

編輯:

我做了一些快速,你們認爲有關的解決方案是什麼,它不是最通用的一個,只是現在沒有更好的主意:

當程序試圖寫入文件時,檢查它是否被使用。如果使用它在內存中收集數據,只要應用程序想要再次寫入文件並且文件是空閒的,則插入所有數據。

它仍然不是最好的,但它可能會提供更多的想法。

+0

你如何打開文件?你可以在'FileStream'構造函數中使用'FileShare.ReadWrite'參數嗎?請參閱http://msdn.microsoft.com/en-us/library/5h0z48dh.aspx – Gabe

+0

相關問題http://stackoverflow.com/questions/3808474/whats-the-right-pattern-for-waiting-on-a -file-lock-to-be-released – PeskyGnat

+0

@Gabe我正在使用StreamWriter。當我讀取文件時,我需要讀出所有的數據直到最後,當我插入數據到最後。如果我分享這個文件,會不會得到小狗(丟失數據)? – Daniel

回答

3

由於您的應用程序正在讀取和寫入文件,所以您只需跟蹤應用程序正在使用的文件即可。保留一個由文件名鍵控的R/W locks字典。當你去訪問一個文件時,取出適當的鎖。

下面是你可以編寫它:

Dictionary<string, ReaderWriterLockSlim> lockDict = new Dictionary<string, ReaderWriterLockSlim>(); 

ReaderWriterLockSlim LockFile(string filename, bool readOnly) 
{ 
    var fullPath = System.IO.Path.GetFullPath(filename); 
    ReaderWriterLockSlim myLock; 
    // lock the dictionary while we're accessing it 
    lock (lockDict) 
    { 
     if (!lockDict.TryGetValue(fullPath, out myLock)) 
     { 
      myLock = new ReaderWriterLockSlim(); 
      lockDict[fullPath] = myLock; 
     } 
    } 
    // only block on the file lock once the dictionary is unlocked 
    if (readOnly) 
     myLock.EnterReadLock(); 
    else 
     myLock.EnterWriteLock(); 
    // file is now "locked", so caller can proceed with read/write, then unlock 
    return myLock; 
} 

,你可能會使用這樣的:

// block until we're not using the file anymore 
var myLock = LockFile(filename, readOnly: false); 
try 
{ 
    using (var file = new StreamWriter(filename)) 
    { 
    ... 
    } 
} 
finally 
{ 
    myLock.ExitWriteLock(); 
} 
+0

'try-finally'模塊對於確保寫入鎖定被釋放的使用示例可能效果最佳。 –

+0

@Scott:在文件關閉之前,您不想冒退出文件鎖的風險,所以我沒有用'finally'來實現它。 – Gabe

+0

如果嘗試包含使用塊,則文件鎖定將在最終觸發之前釋放。 'var myLock = ...;嘗試{using(var file = new StreamWriter(filename)){...}} finally {myLock.ExitWriteLock(); ''或者我在某個地方有一個不正確的假設? –