代码之家  ›  专栏  ›  技术社区  ›  Vinko Vrsalovic

加速文件。对于不存在的网络共享存在

  •  32
  • Vinko Vrsalovic  · 技术社区  · 15 年前

    我必须检查一组文件路径是否代表现有文件。

    它工作正常,除非路径包含不在当前网络上的计算机上的网络共享。在这种情况下,超时需要相当长的时间(30或60秒)。

    问题

    • 有没有办法缩短不存在的网络共享的超时时间?(我确信,当它们确实存在时,它们会快速响应,因此超时1秒就可以了)

    更新:使用线程工作,但不是特别优雅

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

    此解决方案避免了每次尝试都需要一个线程,首先检查哪些驱动器是可访问的,并将其存储在某个位置。


    Experts exchange solution

    首先,您可以在IsDriveReady函数中设置一个“timeout”值。我把它设置为5秒,但设置为任何适合你的。

    以下使用3种方法:

    1. 第一个是WNetGetConnection API函数,它获取 驱动器的UNC(\servername\share)
    2. 第二个是我们的主要方法:Button1\u Click事件

    这对我来说太棒了!干得好:

    '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
    
    6 回复  |  直到 9 年前
        1
  •  8
  •   Community pid    7 年前

    简而言之

    1. 生成可用驱动器的列表。
    2. UNC 名称
    3. ping 开车。

    编辑比尔的评论

    OP找到了我在原始答案中提到的那篇文章,并很友好地将其包括在内 the source code for the solution

        2
  •  4
  •   Nick    15 年前

    使用线程进行检查。我认为线程可以超时。

        3
  •  4
  •   Jan 'splite' K.    6 年前

    /// <sumary>Check if file exists with timeout</sumary>
    /// <param name="fileInfo">source</param>
    /// <param name="millisecondsTimeout">The number of milliseconds to wait,
    ///  or <see cref="System.Threading.Timeout.Infinite"/> (-1) to wait indefinitely.</param>
    /// <returns>Gets a value indicating whether a file exists.</returns>
    public static bool Exists(this FileInfo fileInfo, int millisecondsTimeout)
    {
        var task = new Task<bool>(() => fileInfo.Exists);
        task.Start();
        return task.Wait(millisecondsTimeout) && task.Result;
    }
    

    资料来源: http://www.jonathanantoine.com/2011/08/18/faster-file-exists/

    有人担心“驱动响应不够快”,所以这是速度和“真相”之间的折衷。如果你想百分之百地确定,你就不用它吗。

        4
  •  1
  •   dlchambers    14 年前


    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);
    }
    
        5
  •  0
  •   user2533239    11 年前

    我发现pathExists with thread timeout函数很有用,但最终意识到它需要将File.Exists更改为Directory.Exists才能正常工作。

        6
  •  -1
  •   jay_t55    15 年前