Мне нужно проверить, представляет ли набор путей файлов существующий файл.
Он отлично работает, за исключением случаев, когда путь содержит сетевой ресурс на компьютере, который не находится в текущей сети. В этом случае требуется довольно долгое время (30 или 60 секунд) до истечения времени ожидания.
Вопросы
-
Есть ли способ сократить время ожидания для не существующих сетевых ресурсов? (Я уверен, что когда они действительно существуют, они ответят быстро, поэтому тайм-аут в 1 секунду будет в порядке)
-
Есть ли другой способ решить эту проблему без начала кэширования и сделать алгоритм более сложным? (т.е. я уже знаю, что эти сетевые ресурсы X не существуют, пропустите остальные пути сопоставления)
UPDATE: использование Threads работает, но не особенно элегантно, хотя
public bool pathExists(string path)
{
bool exists = true;
Thread t = new Thread
(
new ThreadStart(delegate ()
{
exists = System.IO.File.Exists(path);
})
);
t.Start();
bool completed = t.Join(500); //half a sec of timeout
if (!completed) { exists = false; t.Abort(); }
return exists;
}
Это решение позволяет избежать необходимости в потоке за попытку, сначала проверить, какие диски доступны, и сохранить где-нибудь.
Экспертное решение для обмена:
Прежде всего, есть значение "тайм-аута", которое вы можете установить в функции IsDriveReady. Я устанавливаю его на 5 секунд, но устанавливаю его для любых работ для вас.
3 метода используются ниже:
- Первой является функция API WNetGetConnection, которая получает UNC (\ имя_сервера\общий) диска
- Второй наш основной метод: событие Button1_Click
- Третья - это функция IsDriveReady, которая пингорует сервер.
Это отлично поработало для меня! Вот вы:
'This API Function will be used to get the UNC of the drive Private Declare Function WNetGetConnection Lib "mpr.dll" Alias _ "WNetGetConnectionA" _ (ByVal lpszLocalName As String, _ ByVal lpszRemoteName As String, _ ByRef cbRemoteName As Int32) As Int32 'This is just a button click event - add code to your appropriate event Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Dim bIsReady As Boolean = False For Each dri As IO.DriveInfo In IO.DriveInfo.GetDrives() 'If the drive is a Network drive only, then ping it to see if it ready. If dri.DriveType = IO.DriveType.Network Then 'Get the UNC (\\servername\share) for the ' drive letter returned by dri.Name Dim UNC As String = Space(100) WNetGetConnection(dri.Name.Substring(0, 2), UNC, 100) 'Presuming the drive is mapped \\servername\share ' Parse the servername out of the UNC Dim server As String = _ UNC.Trim().Substring(2, UNC.Trim().IndexOf("\", 2) - 2) 'Ping the server to see if it is available bIsReady = IsDriveReady(server) Else bIsReady = dri.IsReady End If 'Only process drives that are ready If bIsReady = True Then 'Process your drive... MsgBox(dri.Name & " is ready: " & bIsReady) End If Next MsgBox("All drives processed") End Sub Private Function IsDriveReady(ByVal serverName As String) As Boolean Dim bReturnStatus As Boolean = False '*** SET YOUR TIMEOUT HERE *** Dim timeout As Integer = 5 '5 seconds Dim pingSender As New System.Net.NetworkInformation.Ping() Dim options As New System.Net.NetworkInformation.PingOptions() options.DontFragment = True 'Enter a valid ip address Dim ipAddressOrHostName As String = serverName Dim data As String = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" Dim buffer As Byte() = System.Text.Encoding.ASCII.GetBytes(data) Dim reply As System.Net.NetworkInformation.PingReply = _ pingSender.Send(ipAddressOrHostName, timeout, buffer, options) If reply.Status = Net.NetworkInformation.IPStatus.Success Then bReturnStatus = True End If Return bReturnStatus End Function