开发者

.NET socket timeout - blocking on Close method

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 开发者_如何学Cthe 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:

  • Trace from non-blocking close when using GUI thread
  • Trace from blocking close when using non-GUI thread


Have you tried removing the "MessageBox.Show" calls that you have around the call to Socket.Close()?


What I can't figure is why it closes immediately on the GUI thread. I'd try calling client.Shutdown() before calling client.Close().

I'd also try running the socket object in a regular thread (Thread.Start()) instead of using the ThreadPool. That way you could keep a reference to the thread and call Thread.Interrupt() and/or Thread.Abort() yourself.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜