У меня проблемы с реализацией таймаута подключения с использованием асинхронных вызовов сокетов.
Идея заключается в том, что я вызываю BeginConnect для объекта Socket, а затем использую таймер для вызова 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 может отличаться в зависимости от того, подключен ли он к потоку графического интерфейса или к другому потоку: