I'm having trouble implementing a connect timeout using asynchronous socket calls.
The idea being that I call BeginConnect on a Socket object, then use a timer to call Close() on the socket after a timeout period has elapsed.
This works fine as long as the socket is created on the GUI thread - the Close method returns immediately, and the callback method is executed. However, if the socket is created on any other thread, the Close method blocks until the default IP timeout occurs.
Code to reproduce:
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.");
}
If you remove the QueueUserWorkItem line, creating the socket on the GUI thread, the socket closes instantly without blocking.
Can anyone shed some light on what's going on?
Thanks.
Edit - System.Net trace output seems to be different depending on whether it's being connected on the GUI thread or a different thread: