为非现有网络共享加速File.Exists

时间:2009-08-05 12:30:16

标签: c# networking timeout c#-2.0

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

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

问题

  • 有没有办法缩短非现有网络共享的超时时间? (我确信当他们存在时他们会很快回答,所以超时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;
}

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


Experts exchange solution

  

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

     

下面使用了3种方法:

     
      
  1. 第一个是获取的WNetGetConnection API函数             驱动器的UNC(\ servername \ share)
  2.   
  3. 第二个是我们的主要方法:Button1_Click事件
  4.   
  5. 第三个是ping服务器的IsDriveReady功能。
  6.         

    这对我很有用!你走了:

    '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 个答案:

答案 0 :(得分:7)

简而言之

  1. 构建可用驱动器列表。
  2. 尝试将此驱动器号解析为UNC名称。
  3. 尝试ping驱动器。
  4. 关于比尔评论的编辑

    如果Google不是引用者,则EE不会免费显示答案。 EE的链接没有帮助。

    OP找到了我在原始答案中提到过的文章,并且非常友好地将the source code for the solution包括在他的问题中。

答案 1 :(得分:4)

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

答案 2 :(得分:1)

这对我来说很有用! 这是C#中的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);
}

答案 3 :(得分:0)

我发现带有线程超时功能的pathExists非常有用但终于意识到它需要从File.Exists更改为Directory.Exists才能正常工作。

答案 4 :(得分:0)

另一个“线程解决方案”:

Sub test()
With Sheets("Feuil1")
    .Range("B1").Value = WorksheetFunction.VLookup(.Range("A1").Value, Sheets("Feuil2").Range("A1:B100"), 2, False)
End With
End Sub

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

对于“驱动器响应速度不够快”存在一些担忧,因此这是速度与“真相”之间的折衷。如果您想确定100%,请不要使用它。

答案 5 :(得分:-1)

难道你不能只使用FileMonitor控件,以便在删除事件时触发事件吗?然后你可以将bool设置为false;