加快非现有网络股File.Exists [英] Speed up File.Exists for non existing network shares

查看:133
本文介绍了加快非现有网络股File.Exists的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我要检查如果一组文件路径重新present现有文件。

它的工作原理,当路径包含一台机器,这不是目前网络上的网络共享,除了罚款。在这种情况下,它需要一个pretty长的时间(30或60秒)超时。

问题


  • 有没有办法缩短非现有网络股超时? (我敢肯定,当它们确实存在,他们会快速回答,所以1秒的超时将被罚款)


  • 是否有任何其他方式来解决这个问题,而无需启动缓存,使算法更复杂? (也就是说,我已经知道这些X网络共享不存在,跳过匹配的路径的其余部分)


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

 公共BOOL pathExists(字符串路径)
{
    布尔存在= TRUE;
    线程t =新主题
    (
        新的ThreadStart(委托()
        {
            存在= System.IO.File.Exists(路径);
        })
    );
    t.Start();
    布尔完成= t.Join(500); //半超时的秒
    如果(!完成){存在= FALSE; t.Abort(); }
    返回的存在;
}

该解决方案避免了每尝试一个线程,首先检查该驱动器可访问和存储的地方。


<一href=\"http://www.experts-exchange.com/Programming/Languages/.NET/Visual_Basic.NET/Q_22595703.html\">Experts交换解决方案


  

首先,有一个超时的价值,你可以在IsDriveReady功能设置。我有它设置为5秒,但将其设置为你的作品无论


  
  

3方法如下使用:


  
  

      
  1. 首先是得到了WNetGetConnection API函数
                UNC(\\服务器名\\共享)驱动器

  2.   
  3. 第二个是我们的主要方法:Button1_Click事件

  4.   
  5. 第三个是IsDriveReady函数坪服务器。

  6.   

  
  

这工作对我来说太棒了!在这里你去:

 '这个API函数将被用于获取驱动器的UNC
私人声明函数库WNetGetConnectionMPR.DLL别名_
WNetGetConnectionA_
(BYVAL lpszLocalName作为字符串_
BYVAL lpszRemoteName作为字符串_
为ByRef cbRemoteName作为Int32)已作为的Int32
这只是一个按钮单击事件 - 加code你相应的事件
私人小组的button1_Click(BYVAL发件人为System.Object的,BYVAL E上System.EventArgs)把手Button1.Click    昏暗bIsReady由于布尔= FALSE    对于每个DRI作为IO.DriveInfo在IO.DriveInfo.GetDrives()        如果驱动器是一个网络驱动器只,然后ping到它,看它是否已经准备好。
        如果dri.DriveType = IO.DriveType.Network然后            获取的该UNC(\\\\服务器\\共享)
            通过dri.Name返回驱动器盘符
            昏暗UNC作为字符串=空间(100)
            WNetGetConnection(dri.Name.Substring(0,2),UNC 100)            'presuming的驱动器映射\\\\服务器\\共享
            解析服务器名出的UNC
            昏暗的服务器作为字符串= _
                 。UNC.Trim()子串(2,UNC.Trim()的IndexOf(\\,2) - 2)            坪地看到服务器(如果可用)
            bIsReady = IsDriveReady(服务器)        其他
            bIsReady = dri.IsReady        万一        只有过程的驱动器已准备好
        如果bIsReady = TRUE然后
            处理您的驱动器...
            MSGBOX(dri.Name&安培;准备就绪:&放大器; bIsReady)        万一    下一个    MSGBOX(处理所有驱动器)结束小组专用功能Is​​DriveReady(BYVAL服务器名称作为字符串)作为布尔
    昏暗bReturnStatus由于布尔= FALSE    '***设置你的TIMEOUT HERE ***
    昏暗的超时为整数= 5'5秒    昏暗pingSender作为新System.Net.NetworkInformation.Ping()
    昏暗的选项作为新System.Net.NetworkInformation.PingOptions()    options.DontFragment = TRUE    输入一个有效的IP地址
    昏暗ipAddressOrHostName作为字符串=服务器
    昏暗的数据作为字符串=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
    昏暗的缓冲区作为字节()= System.Text.Encoding.ASCII.GetBytes(数据)
    昏暗的答复,System.Net.NetworkInformation.PingReply = _
                pingSender.Send(ipAddressOrHostName,超时,缓冲,期权)    如果reply.Status = Net.NetworkInformation.IPStatus.Success然后
        bReturnStatus = TRUE    万一    返回bReturnStatus
结束功能



解决方案

使用线程做检查。我认为,线程可以超时。

I have to check if a set of file paths represent an existing file.

It works fine except when the path contains a network share on a machine that's not on the current network. In this case it takes a pretty long time (30 or 60 seconds) to timeout.

Questions

  • Is there a way to shorten the timeout for non existing network shares? (I'm certain that when they do exist they'll answer quickly, so a timeout of 1 sec would be fine)

  • Is there any other way to solve this issue without starting to cache and making the algorithm more complex? (ie, I already know these X network shares don't exist, skip the rest of the matching paths)

UPDATE: Using Threads work, not particularly elegant, though

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

This solution avoids the need for a thread per attempt, first check which drives are reachable and store that somewhere.


Experts exchange solution:

First of all, there is a "timeout" value that you can set in the IsDriveReady function. I have it set for 5 seconds, but set it for whatever works for you.

3 methods are used below:

  1. The first is the WNetGetConnection API function that gets the UNC (\servername\share) of the drive
  2. The second is our main method: The Button1_Click event
  3. The third is the IsDriveReady function that pings the server.

This worked great for me! Here you go:

'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

解决方案

Use Threads to do the checks. I think that threads can be timed out.

这篇关于加快非现有网络股File.Exists的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆