2009-09-17 6 views
12

Io usoFunzione DirectoryExist più veloce?

DirectoryExists (const PathName : String); 

per verificare se una directory è raggiungibile da un computer o meno. Ma se la directory non esiste e il nome del percorso è un percorso di rete, vale a dire

\\computer1\Data 

il metodo prende molto tempo per tornare.

Ci deve essere un modo più rapido per determinare che una cartella di rete non è raggiungibile. Oppure posso configurare un parametro di timeout che DirectoryExists utilizza internamente (ho guardato il codice sorgente ma delegato semplicemente a GetFileAttributes che è definito nel kernel32)?

Qualche idea?

+0

Il problema è che la directory non esiste sul computer remoto o che non è possibile connettersi al computer remoto in primo luogo? –

+0

Potrebbe essere entrambi, ma nella maggior parte dei casi non riesco a connettermi. – jpfollenius

+0

Come contro-esempio mi piacerebbe posare il mio piccolo NAS a casa: quando non lo uso da un po 'i dischi girano verso il basso. Quando accedo per la prima volta alla directory montata, una semplice lista può richiedere circa 20 secondi. Quindi durante quei 20 secondi non c'è modo di sapere se esiste una data directory. Anche dopo 15 secondi non puoi essere sicuro che non esista ... solo quando ottieni una risposta (negativa) reale dall'host puoi essere sicuro che il file non esiste. –

risposta

18

Non c'è modo più veloce:

qualsiasi funzione l'accesso a qualsiasi cosa su una condivisione remota sarà timeout quando tale quota non è disponibile.

Se la causa dei vostri timeout è di disconnessione automatica di azioni, allora questo link possono aiutare: http://support.microsoft.com/default.aspx?scid=kb;[LN];Q138365

Se l'applicazione può continuare senza il completamento della verifica, allora si può mettere il check-in un thread separato e al termine del controllo, puoi aggiornare il tuo stato nell'interfaccia utente.

- jeroen

5

Se si esegue il test su molte directory, è necessario utilizzare i thread per eseguire tutte le query in parallelo, poiché per le condivisioni di rete sono in genere lunghi timeout.

+0

Non sto testando molte directory. Solo per uno. Ma DirectoryExists può richiedere circa 30 secondi per tornare, il che è fastidioso. – jpfollenius

6

c'era la stessa domanda per C#: How to avoid network stalls in GetFileAttributes?

Come ha detto codymanix, utilizzare fili. Il link sopra ti mostrerà come puoi farlo con i delegati in C#. Non conosci Delphi, ma forse sai come convertire il codice?

+3

(i thread sono utili solo se puoi fare qualcosa in parallelo. Se la tua prossima azione dipende dalla condivisione (ad es. Per caricare la configurazione), nel caso del thread ottieni solo la possibilità di mostrare un movimento all'utente, non lo fa accelerare) –

3

Questo è il modo migliore. Potresti aggiungere del codice per eseguire il ping della macchina per assicurarti che esista, ma questo lascerebbe la routine fino a fallire dato che molti computer oggi dispongono di firewall software impostati per ignorare le richieste ping, così come la possibilità che la condivisione richiesta non esistere.

Inoltre, su alcune macchine se il percorso UNC si trova sul computer locale e il computer locale non dispone di una scheda di rete attiva (un laptop con connessione Wi-Fi, ad esempio in modalità "Aereo"), anche le richieste UNC falliscono .

0

Se entrambi i computer si trovano nello stesso dominio, velocizzeranno le operazioni sui file quando si gestiscono le condivisioni.

1

In una situazione simile a quella prescritta, ho aggiunto prima un ping ICMP al server. Se il server non risponde al ping, presumo che non funzioni. È possibile decidere quale timeout utilizzare sul ping autonomamente, in modo da poterlo impostare molto più breve del timeout utilizzato internamente quando si tenta di aprire una condivisione file.

2

Io uso il seguente codice ...

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; 
    } 
} 

... che mi permette di avere una versione timeout di Directory.Exist. Lo chiamo con qualcosa come ...

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

Questo dovrebbe essere adatto alle vostre esigenze?


di essere sicuro/legale, allora avete bisogno di chiamare "callback.EndInvoke (risultato);" ma chiamandolo si blocca fino a quando non termina l'asincrona, quindi questo sconfigge l'oggetto del codice. Forse questo deve essere fatto alla fine del tuo codice - esci forse?