我对TcpClient.BeginConnect()和TcpClient.EndConnect()方法的奇怪行为有疑问。
我使用BeginConnect()为Connect()方法添加超时(请参阅下面的扩展方法代码)。如果我连接,我调用EndConnect()并且一切正常,但如果我超时,我不能调用EndConnect(),因为它会阻塞大约20秒,所以我只是调用这个非阻塞代码: / p>
result.AsyncWaitHandle.Close();
result.AsyncWaitHandle.Dispose();
client.Close();
问题是当我在超时后关闭表单(在运行上面的代码之后),我的应用程序将#34;挂起"大约20秒。
有没有办法防止这种情况发生?
仅在应用程序退出时令人不快,所以如果没有别的办法可能会有一些肮脏的杀戮;]
一些注意事项:
如果我在超时时运行此非阻塞代码:
client.Client.Close();
client.Client.Dispose();
client.Close();
它仍会在退出时挂起。
以下是我的连接代码:
public bool Connect(string localMachineName)
{
// Get ips for local machine
IPAddress[] ips;
try
{
ips = Dns.GetHostEntry(localMachineName).AddressList.Where(
o => o.AddressFamily == AddressFamily.InterNetwork).ToArray();
}
catch { return false; }
// loop and try to connect
foreach (IPAddress ip in ips)
{
TcpClient c = new TcpClient();
try
{
c.NoDelay = true;
c.SendTimeout = 1000; // this seems to not change anything
c.ReceiveTimeout = 1000; // this seems to not change anything
// call connect with timeout - extension method
// this leave after 1 sec (as required) but hangs app on exit
c.Connect(ip, 8888, new TimeSpan(0, 0, 1));
// if you comment previous line and uncomment code line below
// it will block for about 20 secs and not hangs on apps exit
// c.Connect(ip, 8888);
if (c.Connected)
{
MyClient = c;
break;
}
else
{
MyClient = null;
}
}
catch
{
c.Close();
MyClient = null;
}
}
return (MyClient != null) && (MyClient.Connected);
}
以上代码使用扩展方法连接超时,此方法的代码如下(基于某些SO答案的代码):
public static void Connect(this TcpClient client, IPAddress ip, int port, TimeSpan timeout)
{
// begin async connection
IAsyncResult result = client.BeginConnect(ip, port, null, null);
if (result.CompletedSynchronously)
{
client.EndConnect(result);
return;
}
try
{
// wait until connected or timeouted or app shutdown
WaitHandle[] handles = new WaitHandle[] { result.AsyncWaitHandle, shutdownEvent };
int index = WaitHandle.WaitAny(handles, timeout);
if (index == 0)
{
// connected
client.EndConnect(result);
}
else if ((index == 1) || (index == WaitHandle.WaitTimeout))
{
// timeout or app shutdown
/*
* Enabling this will block on EndConnect for about 15-20 seconds
client.EndConnect(result);
client.Close();
return;
*/
/*
* Alternatively, after commenting above I tried this code,
* it doesn't block, but then it hangs for about 20 secs on app exit
client.Client.Close();
client.Client.Dispose();
*/
// this doesn't block, but then it hangs for about 20 secs on app exit
result.AsyncWaitHandle.Close();
result.AsyncWaitHandle.Dispose();
client.Close();
}
}
catch (Exception e)
{
client.Close();
throw new Exception("Connecting with timeout error: " + e.Message);
}
}
我对此问题进行了大量搜索,但无法查看与此特定问题相关的任何信息。请帮忙!