更快的 DirectoryExists 功能?
我用来
DirectoryExists (const PathName : String);
检查目录是否可以从计算机访问。但如果该目录不存在并且路径名是网络路径,即
\\computer1\Data
该方法需要很长时间才能返回。
必须有一种更快的方法来确定网络文件夹不可访问。或者我可以配置 DirectoryExists 内部使用的一些超时参数(我查看了源代码,但它只是委托给 kernel32 中定义的 GetFileAttributes)?
有什么想法吗?
I use
DirectoryExists (const PathName : String);
to check if a directory is reachable from a computer or not. But if the directory does not exist and the path name is a network path, i.e.
\\computer1\Data
the method takes a very long time to return.
There must be a faster way to determine that a network folder is not reachable. Or can I configure some timeout parameter that DirectoryExists uses internally (I looked at the source code but it just delegates to GetFileAttributes which is defined in kernel32)?
Any ideas?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
没有更快的方法:
当该共享不可用时,访问远程共享上任何内容的任何函数都会超时。
如果超时的原因是自动断开共享,那么这些链接可能会帮助您:
如果应用程序可以在未完成检查的情况下继续,那么您可以将在单独的线程中进行检查,检查完成后,您可以在 UI 中更新您的状态。
请注意,当您尝试多线程方式时,您必须证明您的代码不存在竞争条件和内存泄漏。超时与异常相结合通常会使这成为一项艰巨的任务。
There is no faster way:
any function accessing anything on a remote share will timeout when that share is not available.
If the cause of your timeouts is automatic disconnecting of shares, then these link may help you:
If the application can continue without the completion of the check, then you can put the check in a separate thread, and upon completion of the check, you can update your status in the UI.
Be aware that when you try a multi-threading way, that you have to disprove your code is free of race-conditions and memory leaks. Time-outs in combination with exceptions usually make that a hard task.
C# 也有同样的问题:
如何避免 GetFileAttributes 中的网络停顿?
正如 codymanix 所说,使用线程。上面的链接将向您展示如何使用 C# 中的委托来完成此操作。不懂Delphi,但也许你知道如何转换代码?
There was the same question for C#:
How to avoid network stalls in GetFileAttributes?
As codymanix said, use threads. The above link will show you how you can do it with delegates in C#. Don't know Delphi, but maybe you know how to convert the code?
如果您测试大量目录,您应该使用线程并行执行所有查询,因为对于网络共享,通常会有很长的超时。
If you test for lots of directories you should use threads to do all the queries in parallel because for network shares ther are usually long timeouts.
这个函数对我来说非常有效:
NetDirectoryExists(Path, Timeout)
它使用线程,是
TDirectory.Exists(Path)
的完美替代品用法:
if NetDirectoryExists('\\computer1\Data', 1000) then ...
if NetDirectoryExists('C:\Folder', 500) then ...
如果文件夹存在,该函数只需要几毫秒,与不存在的文件夹(
C:\NotExisting
)相同。如果它是不可访问的网络路径(\\ServerNotReady\C$
),那么它将消耗第二个参数给出的毫秒数。This function worked for me very well:
NetDirectoryExists(Path, Timeout)
It uses Threading and is the perfect alternative for
TDirectory.Exists(Path)
Usage:
if NetDirectoryExists('\\computer1\Data', 1000) then ...
if NetDirectoryExists('C:\Folder', 500) then ...
If the Folder exists, the function needs only some milliseconds, same with not existing folders (
C:\NotExisting
). If it is a not reachable network path (\\ServerNotReady\C$
) then it will consume the number of milliseconds given by the second parameter.这是最好的办法。您可以添加一些代码来 ping 机器以确保它存在,但这仍然会使例程失败,因为当今许多计算机都设置了软件防火墙来忽略 ping 请求,并且请求的共享也有可能不存在存在。
此外,在某些计算机上,如果 UNC 路径位于本地计算机上并且本地计算机没有活动网卡(例如处于“飞行”模式的 Wi-Fi 断开连接的笔记本电脑),则 UNC 请求也会失败。
This is the best way. You could add some code to ping the machine to insure it exists, but this would still leave the routine up to fail as many computers today have software firewalls set up to ignore ping requests, as well as the possibility that the share requested doesn't exist.
Also, on some machines if the UNC path is on the local machine and the local machine does not have an active network card (a wi-fi disconnected laptop for instance in "Airplane" mode) then UNC requests will also fail.
我使用以下代码...
...这允许我拥有 Directory.Exist 的超时版本。我用诸如...这样的名称来称呼它,
这可以满足您的需求吗?
为了安全/合法,你需要调用“callback.EndInvoke(result);”但调用它会锁定直到异步完成,因此这会破坏代码的对象。也许这需要在代码末尾完成 - 也许退出?
I use the following code...
...which allows me to have a timeout version of Directory.Exist. I call it with something like...
Would this be OK for you needs?
To be safe/legal then you need to call "callback.EndInvoke(result);" but calling it locks until the async finishes so this defeats the object of the code. Perhaps this needs to be done at the end of you code - exit maybe?
在与您规定的类似情况下,我首先向服务器添加了 ICMP ping。如果服务器没有响应 ping,我认为它已关闭。您可以自己决定在 ping 上使用哪个超时,因此可以将其设置为比尝试打开文件共享时内部使用的超时短得多。
In a similar situation like you prescribed, I've added an ICMP ping to the server first. If the server doesn't respond to the ping, I assume it is down. You can decide which timeout to use on the ping yourself, so you can set it much shorter than the timeout used internally when trying to open a file-share.
如果两台计算机位于同一域中,则在处理共享时将加快文件操作速度。
If both computers are on the same domain it will speed-up file operations when dealing with shares.