2

How can setting a custom timeout for BeginConnect async call be accomplished in c#? It is very useful, while connecting to a host with a chance of not listening on given port. Each such call wastes around 15s of time before releasing the Thread.

I have following code, as advised in many stackoverflow answers:

public bool Test()
{
     using (var tcp = new TcpClient())
     {
         var c = tcp.BeginConnect(IPAddress.Parse("8.8.8.8"), 8080, null, null);
         var success = c.AsyncWaitHandle.WaitOne(TimeSpan.FromSeconds(1));

         if (!success)
         {
             Console.WriteLine("Before cleanup");
             tcp.Close();
             tcp.EndConnect(c);
             Console.WriteLine("After cleanup");
             throw new Exception("Failed to connect.");
         }
     }

     return true;
}

However this does not work. Indeed after the call, the function enters the "if" switch but it blocks immediately on tcp.Close() call and waits for mentioned 15s. Can it be avoided somehow?

Josh
  • 81
  • 1
  • 3
  • 7
  • possible duplicate of [How to set the timeout for a TcpClient?](http://stackoverflow.com/questions/17118632/how-to-set-the-timeout-for-a-tcpclient) Also, what's with the manual disposing *and* the using statement? – bzlm Jan 26 '15 at 21:29
  • Thanks for commenting, however it does not matter whether "using" is present or not. Your linked solution does not work, and is present in my code. This is similar problem as here: http://stackoverflow.com/questions/27417990/app-hangs-for-20-secs-on-exit-after-tcpclient-beginconnect – Josh Jan 26 '15 at 21:31
  • do you find solution? – shahroz May 09 '16 at 07:22
  • It was kaspersky. It's interferring with network traffic on common ports such as 8080 and DNS (53). Try to uninstall and test. – Josh May 22 '16 at 09:01

1 Answers1

0

I wrote a simple test program, using two different techniques for accomplishing your goal, as well as also testing the exact code you posted. I was unable to reproduce the problem you are describing. Whether I use TcpClient or Socket directly, calling Close() on the object results in the connection operation completing immediately (well, in less than 1/10th of a second, after all the async completion, exception handling, thread synchronization, etc.)

Do note that in the TcpClient case, the TcpClient class seems to have a bug in that it throws NullReferenceException instead of (as one would expect) ObjectDisposedException. This appears to be because TcpClient sets the Client property to null when Close() is called, but then tries to use that value when invoking the completion delegate. Oops.

That means that in your code, the caller would see NullReferenceException instead of the Exception you seem to want to throw. But that doesn't seem like it would cause an actual delay per se.

Here is my test program:

class Program
{
    static void Main(string[] args)
    {
        _TestWithSocket();
        _TestWithTcpClient();

        try
        {
            _TestSOCode();
        }
        catch (Exception e)
        {
            Console.WriteLine("Exception: " + e);
        }
    }

    private static void _TestSOCode()
    {
        using (var tcp = new TcpClient())
        {
            var c = tcp.BeginConnect(IPAddress.Parse("8.8.8.8"), 8080, null, null);
            var success = c.AsyncWaitHandle.WaitOne(TimeSpan.FromSeconds(1));

            if (!success)
            {
                Console.WriteLine("Before cleanup");
                tcp.Close();
                tcp.EndConnect(c);
                Console.WriteLine("After cleanup");
                throw new Exception("Failed to connect.");
            }
        }
    }

    private static void _TestWithTcpClient()
    {
        TcpClient client = new TcpClient();
        object o = new object();

        Console.WriteLine("connecting TcpClient...");
        client.BeginConnect("8.8.8.8", 8080, asyncResult =>
        {
            Console.WriteLine("connect completed");

            try
            {
                client.EndConnect(asyncResult);
                Console.WriteLine("client connected");
            }
            catch (NullReferenceException)
            {
                Console.WriteLine("client closed before connected: NullReferenceException");
            }
            catch (ObjectDisposedException)
            {
                Console.WriteLine("client closed before connected: ObjectDisposedException");
            }

            lock (o) Monitor.Pulse(o);
        }, null);

        Thread.Sleep(1000);

        Stopwatch sw = Stopwatch.StartNew();
        client.Close();

        lock (o) Monitor.Wait(o);
        Console.WriteLine("close took {0:0.00} seconds", sw.Elapsed.TotalSeconds);
        Console.WriteLine();
    }

    private static void _TestWithSocket()
    {
        Socket socket = new Socket(SocketType.Stream, ProtocolType.Tcp);
        object o = new object();

        Console.WriteLine("connecting Socket...");
        socket.BeginConnect("8.8.8.8", 8080, asyncResult =>
        {
            Console.WriteLine("connect completed");

            try
            {
                socket.EndConnect(asyncResult);
                Console.WriteLine("socket connected");
            }
            catch (ObjectDisposedException)
            {
                Console.WriteLine("socket closed before connected");
            }

            lock (o) Monitor.Pulse(o);
        }, null);

        Thread.Sleep(1000);

        Stopwatch sw = Stopwatch.StartNew();
        socket.Close();

        lock (o) Monitor.Wait(o);
        Console.WriteLine("close took {0:0.00} seconds", sw.Elapsed.TotalSeconds);
        Console.WriteLine();
    }
}

Unfortunately, you have not provided an actual complete code example demonstrating the problem. If in your environment the above code demonstrates the problem you describe then, since it doesn't do so in my environment, that obviously means there's something about your environment causing the problem. Different OS version, different .NET version, etc.

In that case, you should be specific about the particular aspect of your environment that might be relevant.

If the above code example works as desired, and does not demonstrate the problem you describe, then you simply need to figure out what is in the code you have that is different and causing the problem. In that case, if you still can't actually figure out the problem, you should post a minimal, complete code example that demonstrates the problem.

Community
  • 1
  • 1
Peter Duniho
  • 68,759
  • 7
  • 102
  • 136
  • Still does not function properly. I'm using VS 2013, NET 4.5.1 in project properties. Win 8.1 fully patched. I just ran the code you mentioned as console project (Release) and i got Socket -> 20s, TcpClient -> 20s, myCode -> 20s. SS: http://gyazo.com/fb0d640045c18517d2d7524fa9619efe I've also asked my friend to run your code, same results. – Josh Jan 31 '15 at 23:08
  • Sorry...sounds like you (and your friend, now) are looking for some specific configuration issue on your computer. I have tested the code myself on a variety of configurations, including one that matches yours as well as on some Windows 7 machines, and they all work correctly. The code itself is fine, which leaves only some problem with your specific computer's configuration (something in .NET, or possibly an issue with the specific network drivers and/or hardware configuration). – Peter Duniho Jan 31 '15 at 23:27
  • Would you be so kind and compile release binary for me with code above? I'll also try to compile my own and test it in on "fresh" windows 7 virtual machine. If your binary works.. then surely VS/.NET issue. – Josh Feb 01 '15 at 16:02
  • @Josh: I'm not sure how you would like me to deliver a compiled binary you. Also, at least given my limited knowledge of the deeper aspects of the Windows network implementation, since we do not know what environmental difference is causing the problem, it's premature to think that even on a "fresh Windows 7 VM", you would not experience the same issue. I.e. it's possible there's something about your local network environment that triggers some behavior in Windows or in .NET that causes this delay. If you have a place you want me to put a binary, I can, but don't get your hopes up. – Peter Duniho Feb 01 '15 at 18:50
  • I've managed to test the binary on fresh Win7 and Win8 installation. It works properly, closing connection in less than 0.02s. This means some software is messing things up on my PC. The one common thing me and my friend have is Kaspersky Antivirus software. I will dig deeper into issue later on and post my research results. – Josh Feb 03 '15 at 00:21
  • @Josh: I can't say for sure that your AV software is the problem. But, I can say with certainty that it is not at all _uncommon_ for AV software to cause all kinds of weird behaviors, including this _kind_ of thing. AV software replaces or intercepts a wide variety of OS functions, including networking, and can introduce unusual and even undesirable behaviors. Of course, the easiest test is to simply temporarily disable the software and run a test like that; often, whatever the AV software is doing, it won't do it when disabled. – Peter Duniho Feb 03 '15 at 02:08