我在使用異步套接字調用實現連接超時時遇到問題。.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