我在使用异步套接字调用实现连接超时时遇到问题。.NET套接字超时 - 在关闭方法上阻塞
这个想法是我在一个Socket对象上调用BeginConnect,然后在超时时间结束后使用定时器在套接字上调用Close()。
只要在GUI线程上创建套接字,Close方法立即返回,并执行回调方法,这就可以正常工作。但是,如果套接字是在任何其他线程上创建的,则Close方法会阻塞,直到发生默认IP超时。
代码重现:
private Socket client;
private void button1_Click(object sender, EventArgs e) {
// Creating the socket on a threadpool thread causes Close to block.
ThreadPool.QueueUserWorkItem((object state) => {
client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IAsyncResult result = client.BeginConnect(IPAddress.Parse("144.1.1.1"), 23, new AsyncCallback(CallbackMethod), client);
// Wait for 2 seconds before closing the socket.
if (result.AsyncWaitHandle.WaitOne(2000)) {
MessageBox.Show("Connected.");
} else {
MessageBox.Show("Timed out. Closing socket...");
client.Close();
MessageBox.Show("Socket closed.");
}
});
}
private void CallbackMethod(IAsyncResult result) {
MessageBox.Show("Callback started.");
Socket client = result.AsyncState as Socket;
try {
client.EndConnect(result);
} catch (ObjectDisposedException) {
}
MessageBox.Show("Callback finished.");
}
如果删除QueueUserWorkItem线上,GUI线程创建的插座,插座会马上闭合而不会阻塞。
任何人都可以阐明发生了什么?
谢谢。
编辑 - System.Net跟踪输出似乎取决于是否它被连接GUI线程或者不同的线程上是不同的:
- Trace from non-blocking close when using GUI thread
- Trace from blocking close when using non-GUI thread
无论MessageBox.Show如何,封闭都会发生。 即使将套接字的[LingerState](http://msdn.microsoft.com/en-us/library/system.net.sockets.socket.lingerstate.aspx)属性设置为true,但不会超时帮帮我。 从MSDN:“下表描述了对于Enabled属性和LingerTime属性中存储的LingerState属性的可能值的Close方法的行为。” 启用LingerState并且将LingerTime设置为零:“丢弃任何未决数据。对于面向连接的套接字(例如TCP),Winsock重置连接。” – Mark 2010-06-05 03:52:06
我试着用上面的程序重新编译。我无法复制它。该程序不挂。 – feroze 2010-06-08 03:16:47
在Windows 7和XP模式下,在任何版本的.NET Framework上,都会出现这种情况。我也可以在不同的机器上重现它。该程序不应该挂起,但在“超时,关闭套接字...”消息和“套接字关闭”之间应该有大约20秒的延迟。信息。 – Mark 2010-06-10 20:51:29