.NET套接字超时 - 在Close方法上阻塞

时间:2010-06-04 08:46:57

标签: c# .net sockets

我在使用异步套接字调用实现连接超时时遇到问题。

我的想法是在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线程上连接还是在另一个线程上连接:

2 个答案:

答案 0 :(得分:0)

您是否尝试删除围绕Socket.Close()调用的“MessageBox.Show”调用?

答案 1 :(得分:0)

我无法想象的是它在GUI线程上立即关闭的原因。我在调用client.Close()。

之前尝试调用client.Shutdown()

我还尝试在常规线程(Thread.Start())中运行套接字对象,而不是使用ThreadPool。这样你就可以保持对线程的引用并自己调用Thread.Interrupt()和/或Thread.Abort()。