我必须检查一组文件路径是否代表现有文件。
除非路径包含不在当前网络上的计算机上的网络共享,否则它可以正常工作。在这种情况下,超时需要很长时间(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种方法:
- 第一个是获取的WNetGetConnection API函数 驱动器的UNC(\ servername \ share)
- 第二个是我们的主要方法:Button1_Click事件
- 第三个是ping服务器的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
答案 0 :(得分:7)
UNC
名称。ping
驱动器。如果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;