当另一个线程/进程使用独占锁时,是否可以绕过C#中的文件锁?

时间:2009-12-29 23:38:28

标签: c# .net file

有没有办法绕过或删除另一个线程持有的文件锁而不杀死该线程?

我在我的应用中使用的第三方库正在对文件执行只读操作。我需要第二个线程同时读取文件以提取第三方库未公开的一些额外数据。不幸的是,第三方库使用读/写锁打开文件,因此我得到通常的“进程无法访问文件......因为它正被另一个进程使用”异常。

我想避免使用我的线程预先加载整个文件,因为文件很大并且会导致加载此文件和内存使用量过大造成不必要的延迟。由于文件的大小,复制文件是不实际的。在正常操作期间,两个线程命中同一文件不会导致任何重大的IO争用/性能问题。我不需要在两个线程之间进行完美的时间同步,但是他们需要在半秒内读取相同的数据。

我无法更改第三方库。

这个问题有解决办法吗?

7 个答案:

答案 0 :(得分:5)

如果您启动messing with the underlying file handle,您可以解锁部分,问题是访问该文件的线程不是为处理这种篡改而设计的,最终可能会崩溃。

我强烈建议修补第三方图书馆,你做的任何事情都可能,并且可能会在现实条件下爆炸。

答案 1 :(得分:2)

简而言之,您无法对第三方锁定文件做任何事情。你可以通过上面提到的Richard E的答案来解决实用程序Unlocker。

一旦第三方打开文件并对其设置锁定,底层系统将为该第三方提供锁定,以确保没有其他进程可以访问它。对此有两种思路。

  • 使用DLL注入修补代码以显式设置锁定或取消设置锁定。这可能是危险的,因为你会弄乱另一个进程的稳定性,并可能最终导致进程崩溃并导致悲痛。考虑一下,底层系统跟踪进程打开的文件......当时注入DLL并修补代码 - 这需要技术知识来确定您希望在运行时注入哪个进程并更改标志拦截Win32 API调用OpenFile(...)
  • 由于这被标记为.NET,为什么不将第三方的源代码转换为.il文件,并将锁的标志更改为共享,通过将所有.il文件重新编译为DLL来重建库。当然,这需要根据代码中的某些类在某个类中进行文件打开。

查看播客here。并在此处查看解释如何执行上面突出显示的第二个选项here

希望这有帮助, 最好的祝福, 汤姆。

答案 2 :(得分:1)

这并不能直接解决您的情况,但像Unlocker这样的工具可以帮助您实现目标,但需要通过Windows用户界面。

答案 3 :(得分:1)

  

执行此操作的任何低级别攻击都可能导致线程崩溃,文件损坏等。

因此,我认为我会提到下一个最好的事情,只需轮到你轮询直到文件没有锁定:https://stackoverflow.com/a/11060322/495455

<小时/> 我不认为这第二个建议会有所帮助,但最接近的事情(我知道)将是DemandReadFileIO

IntSecurity.DemandReadFileIO(filename);

internal static void DemandReadFileIO(string fileName) 
{
   string full = fileName;            
   full = UnsafeGetFullPath(fileName); 
   new FileIOPermission(FileIOPermissionAccess.Read, full).Demand();
}

答案 4 :(得分:1)

我认为这是一个可以用c ++解决的问题。它令人讨厌,但至少它有效(如下所述:win32 C/C++ read data from a "locked" file

步骤如下:

  1. 使用fsopen和_SH_DENYNO标志
  2. 在第三个库之前打开文件
  3. 使用第三个库
  4. 打开文件
  5. 阅读代码中的文件
  6. 您可能也对这些链接感兴趣:

    1. 从c#(Possible to call C++ code from C#?
    2. 调用c ++
    3. 此帖子的内部链接带有示例(http://blogs.msdn.com/b/borisj/archive/2006/09/28/769708.aspx

答案 5 :(得分:1)

您是否尝试在第三方库获取之前制作文件的虚拟副本...然后使用实际副本进行操作,从逻辑上讲,只有在我们讨论的文件是相当小。但这是一种骗子:)祝你好运

答案 6 :(得分:1)

如果文件被锁定且未被使用,那么您的文件锁定/解锁机制的工作方式就会出现问题。您只应在修改文件时锁定文件,然后立即将其解锁以避免这种情况。