更快DirectoryExists功能?

问题描述 投票:14回答:8

我用

DirectoryExists (const PathName : String);

检查目录是从计算机或无法访问。但是,如果该目录不存在和路径名的网络路径,即

\\computer1\Data

该方法需要很长的时间来恢复。

必须有确定的网络文件夹不可达更快的方法。或者,我可以配置DirectoryExists一些内置的超时参数(我看了看源代码,但是这是在KERNEL32定义,它只是委托给GetFileAttributes)?

有任何想法吗?

delphi networking delphi-2009
8个回答
19
投票

有没有更快的方法:

当共享不可用远程共享访问任何任何功能将超时。

如果超时的原因是股票自动断开,然后将这些链接可以帮助你:

如果应用程序可以继续,而不检查完成,那么你可以把检查在一个单独的线程,检查完成后,您可以更新用户界面中的状态。

请注意,当您尝试一个多线程的方式,你要反驳你的代码是免费的比赛条件和内存泄漏。与例外组合超时通常作出这样一个艰巨的任务。


6
投票

有人支持C#同样的问题:How to avoid network stalls in GetFileAttributes?

作为codymanix说,使用线程。上面的链接会告诉你如何可以在C#中的代表做。不知道德尔福,但也许你知道如何将代码转换?


5
投票

如果您测试大量的目录,你应该使用线程来完成所有的并行,是因为网络股疗法通常是长期超时查询。


3
投票

这是最好的方式。你可以添加一些代码来ping计算机,以确保它的存在,但是这仍然会离开例行高达失败,因为许多计算机今天软件防火墙设置为忽略ping请求,以及可能请求该份额不存在。

此外,在一些机器上,如果UNC路径是在本地机器上,并在本地机器没有活动的网络卡(无线网络连接断开连接的笔记本电脑,例如在“飞机”模式),则UNC请求也将失败。


2
投票

在类似的情况就像你规定的,我首先增加了一个ICMP的ping服务器。如果服务器不响应ping,我认为这是下跌。您可以决定在平自己使用的超时,所以你可以把它远比试图打开一个文件共享时内部使用的超时时间更短。


2
投票

我使用下面的代码...

private delegate bool DirectoryExistsDelegate(string folder);

bool DirectoryExistsTimeout(string path, int millisecondsTimeout)
{
    try
    {
        DirectoryExistsDelegate callback = new DirectoryExistsDelegate(Directory.Exists);
        IAsyncResult result = callback.BeginInvoke(path, null, null);

        if (result.AsyncWaitHandle.WaitOne(millisecondsTimeout, false))
        {
            return callback.EndInvoke(result);
        }
        else
        {
            callback.EndInvoke(result);  // Needed to terminate thread?

            return false;
        }
    }

    catch (Exception)
    {
        return false;
    }
}

......这让我有Directory.Exist的超时版本。我把它的东西,如...

bool a = DirectoryExistsTimeout("\\\\machine\\folder", 5000);

这会不会对你的需求确定?


为了安全起见/法律,那么你需要调用“callback.EndInvoke(结果);”但调用它锁定,直到异步完成所以这违背了代码的对象。也许这需要在你的代码到底做了些什么 - 也许退出?


0
投票

如果两台计算机都在同一个域中的股份时,它会加快更新文件的操作。


0
投票

此功能为我工作得非常好:NetDirectoryExists(Path, Timeout) 它使用线程,是TDirectory.Exists(Path)完美替代

用法: if NetDirectoryExists('\\computer1\Data', 1000) then ... if NetDirectoryExists('C:\Folder', 500) then ...

如果该文件夹存在,该功能只需要几毫秒,同时与不存在的文件夹(C:\NotExisting)。如果它是一个不可达网络路径(\\ServerNotReady\C$),那么它会消耗由第​​二个参数给出的毫秒数。

Function NetDirectoryExists( const dirname: String; 
                              timeoutMSecs: Dword ): Boolean; 

implementation 


uses 
   Classes, Sysutils, Windows; 


type 
   ExceptionClass = Class Of Exception; 
   TTestResult = (trNoDirectory, trDirectoryExists, trTimeout ); 
   TNetDirThread = class(TThread) 
   private 
     FDirname: String; 
     FErr    : String; 
     FErrclass: ExceptionClass; 
     FResult : Boolean; 
   protected 
     procedure Execute; override; 
   public 
     Function TestForDir( const dirname: String; 
                timeoutMSecs: Dword ):TTestResult; 
   end; 


Function NetDirectoryExists( 
            const dirname: String; timeoutMSecs: Dword ): Boolean; 
 Var 
   res: TTestResult; 
   thread: TNetDirThread; 
 Begin 
   Assert( dirname <> '', 'NetDirectoryExists: dirname cannot be empty.' ); 
   Assert( timeoutMSecs > 0, 'NetDirectoryExists: timeout cannot be 0.' ); 
   thread:= TNetDirThread.Create( true ); 
   try 
     res:= thread.TestForDir( dirname, timeoutMSecs ); 
     Result := res = trDirectoryExists; 
     If res <> trTimeout Then 
       thread.Free; 
     {Note: if the thread timed out it will free itself when it finally 
      terminates on its own. } 
   except 
     thread.free; 
     raise 
   end; 
 End; 


procedure TNetDirThread.Execute; 
 begin 
   try 
     FResult := DirectoryExists( FDirname ); 
   except 
     On E: Exception Do Begin 
       FErr := E.Message; 
       FErrclass := ExceptionClass( E.Classtype ); 
     End; 
   end; 
 end; 


function TNetDirThread.TestForDir(const dirname: String; 
   timeoutMSecs: Dword): TTestResult; 
 begin 
   FDirname := dirname; 
   Resume; 
   If WaitForSingleObject( Handle, timeoutMSecs ) = WAIT_TIMEOUT 
   Then Begin 
     Result := trTimeout; 
     FreeOnTerminate := true; 
   End 
   Else Begin 
     If Assigned( FErrclass ) Then 
       raise FErrClass.Create( FErr ); 
     If FResult Then 
       Result := trDirectoryExists 
     Else 
       Result := trNoDirectory; 
   End; 
 end; 
© www.soinside.com 2019 - 2024. All rights reserved.