2013-05-28 56 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(); ''或者我在某个地方有一个不正确的假设? –