加快非现有的网络股File.Exists(Speed up File.Exists for non

2019-06-28 01:02发布

我要检查如果一组文件路径代表一个现有的文件。

它的工作原理,当路径中包含一台机器,这不是目前网络上的网络共享,除了罚款。 在这种情况下,它需要一个相当长的时间(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;
}

该解决方案避免了每尝试一个线程,首先检查该驱动器是访问,并储存在某处的需要。


专家交换解决方案

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

3种方法如下使用:

  1. 第一个是WNetGetConnection API函数获取的驱动器的UNC(\服务器\份额)
  2. 第二个是我们的主要方法:Button1_Click事件
  3. 第三是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 

Answer 1:

使用线程来执行检查。 我认为,线程可以超时。



Answer 2:

简而言之

  1. 建立可用驱动器的列表。
  2. 尝试将驱动器号解析为UNC名称。
  3. 尝试ping的驱动器。

关于比尔的评论编辑

如果谷歌不引荐,EE不显示无答案。 链接EE也没有什么帮助。

OP发现我在我原来的答复中提到的文章,还跟包括为解决方案的源代码 ,以他的问题。



Answer 3:

这个伟大的工作对我来说!
这里的IsDriveReady()在C#:

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


Answer 4:

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



Answer 5:

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

/// <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/

有关于“驱动器没有响应速度不够快”一些顾虑,所以这是速度和“真相”之间的妥协。 难道你不使用它,如果你想以确保100%。



Answer 6:

你不能只是使用FileMonitor控制这个,这样,当它被删除的事件触发? 然后,你可以设置布尔为false;



文章来源: Speed up File.Exists for non existing network shares