Я должен проверить, представляет ли набор путей к файлам существующий файл.
Работает нормально, кроме случаев, когда путь содержит общий сетевой ресурс на машине, которой нет в текущей сети. В этом случае тайм-аут занимает довольно много времени (30 или 60 секунд).
Вопросы * * 1005
Есть ли способ сократить время ожидания для несуществующих сетевых ресурсов? (Я уверен, что, когда они существуют, они ответят быстро, поэтому время ожидания в 1 секунду будет в порядке)
Есть ли другой способ решить эту проблему, не начиная кэшировать и не усложняя алгоритм? (т.е. я уже знаю, что эти общие сетевые ресурсы X не существуют, пропустите остальные подходящие пути)
ОБНОВЛЕНИЕ: Работа с потоками работает не очень элегантно, хотя
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;
}
Это решение позволяет избежать необходимости в потоке на попытку, сначала проверьте, какие диски доступны, и сохраните их где-нибудь.
Прежде всего, есть значение «timeout», которое вы можете установить в функции IsDriveReady. У меня он установлен на 5 секунд, но он настроен на то, что вам подходит.
3 метода используются ниже:
- Первая - это функция API WNetGetConnection, которая получает
UNC (\ имя_сервера \ share) диска
- Второй наш основной метод: событие 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's 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