2009-09-17 12 views
12

J'utiliseFonction DirectoryExists plus rapide?

DirectoryExists (const PathName : String); 

pour vérifier si un répertoire est accessible à partir d'un ordinateur ou non. Mais si le répertoire n'existe pas et le nom de chemin est un chemin réseau, à savoir

\\computer1\Data 

la méthode prend beaucoup de temps pour revenir.

Il doit y avoir un moyen plus rapide de déterminer qu'un dossier réseau n'est pas accessible. Ou puis-je configurer un paramètre de délai d'attente que DirectoryExists utilise en interne (j'ai regardé le code source mais il délègue juste à GetFileAttributes qui est défini dans kernel32)?

Des idées?

+0

Le problème est-il que le répertoire n'existe pas sur l'ordinateur distant ou que vous ne pouvez pas vous connecter à l'ordinateur distant en premier lieu? –

+0

Pourrait être les deux, mais dans la plupart des cas je ne peux pas me connecter. – jpfollenius

+0

Pour contre-exemple, j'aimerais poser mon minuscule NAS à la maison: Quand je ne l'ai pas utilisé pendant un moment, les disques se renversent. Lorsque j'accède pour la première fois au répertoire monté, une simple liste peut prendre environ 20 secondes. Donc, pendant ces 20 secondes, il n'y a aucun moyen de savoir s'il existe un répertoire donné là-bas. Même après 15 secondes vous ne pouvez pas être sûr qu'il n'existe pas ... seulement quand vous obtenez une réponse (négative) réelle de l'hôte pouvez-vous être sûr que le fichier n'existe pas. –

Répondre

18

Il n'y a pas moyen plus rapide:

toute fonction accès à quoi que ce soit sur un partage à distance de délai d'attente lorsque cette part est pas disponible.

Si la cause de vos délais d'attente est la déconnexion automatique d'actions, alors ce lien peut vous aider: http://support.microsoft.com/default.aspx?scid=kb;[LN];Q138365

Si l'application peut se poursuivre sans l'achèvement de la vérification, vous pouvez mettre le contrôle dans un thread séparé et, une fois la vérification terminée, vous pouvez mettre à jour votre statut dans l'interface utilisateur.

--jeroen

5

Si vous testez un grand nombre de répertoires, vous devez utiliser des threads pour effectuer toutes les requêtes en parallèle, car les partages réseau sont généralement longs.

+0

Je ne teste pas beaucoup de répertoires. Seulement pour un. Mais DirectoryExists peut prendre environ 30 secondes pour retourner, ce qui est ennuyeux. – jpfollenius

6

Il y avait la même question pour C#: How to avoid network stalls in GetFileAttributes?

Comme dit codymanix, fils d'utilisation. Le lien ci-dessus va vous montrer comment vous pouvez le faire avec des délégués en C#. Je ne sais pas Delphi, mais peut-être savez-vous comment convertir le code?

+3

(les threads ne seront utiles que si vous pouvez faire quelque chose en parallèle.Si votre action suivante dépend du partage (par exemple pour le chargement de la configuration), dans le cas du thread, vous pouvez seulement montrer un mouvement à l'utilisateur. accélérer) –

3

C'est le meilleur moyen. Vous pouvez ajouter du code pour envoyer une requête ping à la machine pour s'assurer qu'elle existe, mais cela laisserait la routine à l'échec car de nombreux ordinateurs ont des pare-feu logiciels configurés pour ignorer les requêtes ping, ainsi que la possibilité que le partage demandé ne fonctionne pas. exister. Sur certaines machines, si le chemin UNC se trouve sur la machine locale et que la machine locale n'a pas de carte réseau active (un ordinateur portable déconnecté par Wi-Fi, par exemple en mode "Avion"), les requêtes UNC échouent également. .

0

Si les deux ordinateurs se trouvent sur le même domaine, les opérations sur les fichiers seront plus rapides.

1

Dans une situation similaire à celle que vous avez prescrite, j'ai d'abord ajouté un ping ICMP au serveur. Si le serveur ne répond pas au ping, je suppose qu'il est en panne. Vous pouvez décider vous-même du délai d'utilisation sur le ping, de sorte que vous pouvez le définir beaucoup plus court que le délai d'attente utilisé en interne lorsque vous essayez d'ouvrir un partage de fichiers.

2

J'utilise le code suivant ...

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

... ce qui me permet d'avoir une version de délai d'attente de Directory.Exist. Je l'appelle avec quelque chose comme ...

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

Est-ce que cela vous convient?


Pour être sûr/légal, vous devez appeler "callback.EndInvoke (result);" mais l'appeler verrouille jusqu'à la fin de l'async, ce qui annule l'objet du code. Peut-être que cela doit être fait à la fin de votre code - sortie peut-être?