【发布时间】:2010-11-17 00:07:48
【问题描述】:
我必须检查一组文件路径是否代表现有文件。
它工作正常,除非路径包含不在当前网络上的计算机上的网络共享。在这种情况下,超时需要相当长的时间(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种方法:
- 第一个是 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
【问题讨论】:
-
是的,我已经投票决定关闭它作为一个骗子。 Chris Pebble 删除了他与问题相关联的答案(我不知道为什么)
-
Expert Exchange 解决方案似乎不太好。文件服务器很可能不响应 ping。这并不意味着它不可用。
-
@mhenry1384 是的。但是,如果您知道它应该响应 ping,它会很有用。如果您想支持 ping 被阻止,您可以尝试连接到 SMB 端口并查看它是否响应...
-
@Kiquenet 线程解决方案是我这些天倾向于使用的。效率很高。
标签: c# networking timeout c#-2.0