2011-12-08 11 views
11

baza kodu mojej firmy zawiera następujące C# linię:Korzystanie Directory.Exists w folderze sieciowym, gdy sieć jest w dół

bool pathExists = Directory.Exists(path); 

przy starcie, ciąg path dzieje się adres folderu na spółki intranet - coś takiego jak \\company\companyFolder. Kiedy połączenie z mojego komputera z systemem Windows do intranetu jest włączone, działa to dobrze. Jednak gdy połączenie zostanie przerwane (jak to miało miejsce dzisiaj), wykonanie powyższej linii spowoduje całkowite zablokowanie aplikacji. Mogę tylko zamknąć aplikację, zabijając ją za pomocą Menedżera zadań.

Oczywiście wolałbym, aby w tym scenariuszu był Directory.Exists(path) wracać false. Czy jest jakiś sposób na zrobienie tego?

Odpowiedz

11

Nie ma możliwości zmiany zachowania Directory.Exists dla tego scenariusza. Pod maską wykonuje synchroniczne żądanie przez sieć w wątku UI. Jeśli połączenie sieciowe zostanie zawieszone z powodu awarii, zbyt dużego ruchu itp., Spowoduje to zawieszenie wątku interfejsu użytkownika.

Najlepszą rzeczą, jaką możesz zrobić, jest wysłanie prośby z wątku w tle i wyraźne zaniechanie po upływie określonego czasu. Na przykład

Func<bool> func =() => Directory.Exists(path); 
Task<bool> task = new Task<bool>(func); 
task.Start(); 
if (task.Wait(100)) { 
    return task.Value; 
} else { 
    // Didn't get an answer back in time be pessimistic and assume it didn't exist 
    return false; 
} 
+3

Może to łatwo zlikwidować wszystkie dostępne wątki w puli wątków, powodując dalsze problemy w aplikacji. Jeśli zamierzasz zrobić coś takiego, musisz mieć możliwość zakończenia operacji po upłynięciu limitu czasu. –

+0

@ csharptest.net to jednak problem, nie możesz. Metoda 'Directory.Exists' nie może być kontrolowana z powodu przekroczenia limitu czasu, a ponieważ w zasadzie natychmiast spada do zdarzenia kodu natywnego,' Thread.Abort' nie pomoże. – JaredPar

1

Jeśli ogóle łączność sieciowa jest podstawowy problem można spróbować testowania połączenia sieciowego przed tym:

[DllImport("WININET", CharSet = CharSet.Auto)] 
    static extern bool InternetGetConnectedState(ref int lpdwFlags, int dwReserved); 

    public static bool Connected 
    { 
     get 
     { 
      int flags = 0; 
      return InternetGetConnectedState(ref flags, 0); 
     } 
    } 

Następnie sprawdzić, czy ścieżka jest ścieżką UNC i return false jeśli sieć jest w trybie offline:

public static bool FolderExists(string directory) 
    { 
     if (new Uri(directory, UriKind.Absolute).IsUnc && !Connected) 
      return false; 
     return System.IO.Directory.Exists(directory); 
    } 

Nic z tego nie pomaga, gdy host, z którym próbujesz się połączyć, jest offline. W takim przypadku nadal trwa 2-minutowy limit czasu sieci.

Powiązane problemy