C#移动操作挂起而不是立即抛出异常

3
有人知道为什么有时候在C#中使用Directory.Move()操作会挂起/等待而不是立即抛出异常吗?
例如: 如果我在try块内使用Directory.Move()方法,然后在文件资源管理器中导航到该文件夹,Windows会创建一些句柄来锁定它。 然后,我期望catch块立即执行,但实际上应用程序似乎会在抛出异常之前挂起10-15秒钟。
有趣的是,如果我在这10-15秒钟内在文件资源管理器中跳出该文件夹,那么应用程序实际上会完成Move()操作。
就好像:Windows会挂起10-15秒钟来看负责句柄(锁)的人是否自行关闭这些句柄,而不是立即抛出异常。
有没有办法使应用程序立即抛出异常?

1
似乎它只是等待文件对象句柄被解锁。当文件/文件夹正在使用时,它是不可删除的,但你不能保证平台会立即中止。它可能会等待一段时间,只有在一些超时后才中止。我非常确定这取决于Windows版本、文件系统类型、注册表驱动程序设置,以及任何侵入性软件,如防病毒软件/监视器/监控器等也会影响到这一点。 - quetzalcoatl
1
请查看此链接 - Sinatr
1
你能使用线程来手动超时这个方法吗?我已经用它来超时检查目录是否存在,但我没有测试移动目录是否也可以工作,因此只是一条注释。类似这样:try { Thread t = new Thread( new ThreadStart(delegate() { Directory.Move(source, dest); })); t.Start(); bool completed = t.Join(1000); if (!completed) { t.Abort(); } } catch { // Whatever } - Equalsk
2
参考来源可以看到,目录移动函数调用了WinAPI的MoveFile函数,这几乎肯定意味着不同操作系统版本之间会有差异。如果你想立即抛出异常,你可以在尝试移动之前检查目录是否被锁定,但这样做存在很大的竞态条件的潜在风险。(例如,在检查锁定和调用移动之间,目录变为锁定状态,你就会回到旧的/缓慢的行为方式。) - theB
@theB 我已经使用了一些检查来确保目录中的文件没有被锁定,而且竞争条件确实很难处理。然而,实际上我没有考虑在尝试移动目录之前检查目录是否被锁定。我会看一下的。谢谢! - Tom K
显示剩余8条评论
1个回答

0
你的问题是“为什么有时候在C#中进行移动操作会挂起/等待而不是立即抛出异常?”的答案可能是,.net框架从其请求NTFS锁的状态中发出Pending状态,并最终放弃。
System.IO.Directory.Move直接映射到Kernel32函数;我猜最终这个函数会调用LockFileEx (https://msdn.microsoft.com/en-us/library/windows/desktop/aa365203(v=vs.85).aspx),它允许调用者指定是否立即失败,如果无法获得锁,则等待指定时间。我猜Kernel32使用了允许设置超时的变体。似乎.net框架对所使用的超时没有任何影响。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接