Подтвердить что ты не робот

Ускорьте файлы File.Exists для не существующих сетевых ресурсов

Мне нужно проверить, представляет ли набор путей файлов существующий файл.

Он отлично работает, за исключением случаев, когда путь содержит сетевой ресурс на компьютере, который не находится в текущей сети. В этом случае требуется довольно долгое время (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
4b9b3361

Ответ 1

Используйте Threads для выполнения проверок. Я думаю, что потоки могут быть отключены.

Ответ 2

В двух словах

  • Создайте список доступных дисков.
  • Попробуйте разрешить буквенное обозначение UNC.
  • Попробуйте ping диск.

Изменить комментарий к комментарию

если Google не является реферирующим, EE не показывает ответ бесплатно. Ссылки на EE не помогают.

OP нашел статью, о которой я упоминал в своем первоначальном ответе, и был достаточно любезен, чтобы включить исходный код для решения в свой вопрос.

Ответ 3

Это работало для меня БОЛЬШИМ!

Здесь IsDriveReady() в С#:

using System.Net;
private bool IsDriveReady(string serverName)
{
   // ***  SET YOUR TIMEOUT HERE  ***     
   int timeout = 5;    // 5 seconds 
   System.Net.NetworkInformation.Ping pingSender = new System.Net.NetworkInformation.Ping();
   System.Net.NetworkInformation.PingOptions options = new System.Net.NetworkInformation.PingOptions();
   options.DontFragment = true;      
   // Enter a valid ip address     
   string ipAddressOrHostName = serverName;
   string data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
   byte[] buffer = System.Text.Encoding.ASCII.GetBytes(data);
   System.Net.NetworkInformation.PingReply reply = pingSender.Send(ipAddressOrHostName, timeout, buffer, options);
   return (reply.Status == System.Net.NetworkInformation.IPStatus.Success);
}

Ответ 4

Я нашел pathExists с функцией тайм-аута потока полезной, но, наконец, понял, что для изменения работы File.Exists в Directory.Exists необходимо правильно работать.

Ответ 5

Не могли бы вы просто использовать элемент управления FileMonitor для этого, чтобы событие срабатывало, когда оно удаляется? Затем вы можете установить bool в false,