Setting WebRequest's Timeout problem in c# .NET

Viewed 40

I'm trying to establish a connection with a FTP server, to achieve this I use WebRequest.Create() with some methods ecc ecc. The problem occurs when the connection can't be established (for example invalid IP address), in fact GetResponse() never returns or returns after a huge amount of time. I tried to set the Timeout property, but either I did something wrong or there is a bug:

  • If I set a number of ms < 16 GetResponse() raises an exception within 100 ms
  • If I set a any number of ms > 16 GetResponse() raises an exception after 21 seconds

I found many post with the Timeout problem but nobody highlight or figure out this particular, any ideas?

            FtpWebRequest request = (FtpWebRequest)WebRequest.Create(uri);
            request.Method = WebRequestMethods.Ftp.ListDirectory;
            request.Credentials = cred;
            request.KeepAlive = false;
            Logger.Write((DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond).ToString());
            request.Timeout = TimeSpan.FromMilliseconds(16).Milliseconds;
            request.GetResponse().Close();

EDIT: Well, I made other tests and actually also with 16 ms or less the timeout is quite random.

My goal is to make the GetResponse() raise an exception within about 300 msec if the connection is impossible to established.

I also try something like this:

 try
 {
    FtpWebRequest request = (FtpWebRequest)WebRequest.Create(uri);
    request.Method = WebRequestMethods.Ftp.ListDirectory;
    request.Credentials = cred;
    request.KeepAlive = false;
    var task = Task.Run(() => request.GetResponse().Close());
    if (!task.Wait(TimeSpan.FromMilliseconds(300)))
    {
        throw new Exception("Timed out");
    }
}
catch (WebException ex)
{
    return false;
}
catch (Exception ex)
{
    return false;
}

With this solution after TimeSpan.FromMilliseconds(300) an exception is raised and the catch block handle it, but after 21 second the Task launched raise another exception which the catch block doesn't handle.

1 Answers

I finally managed to achieve what i was looking for: get an exception if the connection cannot be established within 300 msec.

        try
        {
            FtpWebRequest request = (FtpWebRequest)WebRequest.Create(uri);
            request.Method = WebRequestMethods.Ftp.ListDirectory;
            request.Credentials = cred;
            request.KeepAlive = false;
            var task = Task.Run(() => {
                try
                {
                    request.GetResponse().Close();
                }
                catch { }
            });
            if (!task.Wait(TimeSpan.FromMilliseconds(300)))
                throw new Exception("Timed out");
        }
        catch (WebException ex)
        {
            return false;
        }
        catch (Exception ex)
        {
            return false;
        }

This code raises an exception thanks to task.Wait(), and, when request.GetResponse().Close(); returns with an exception (maybe after 21 seconds) it will be handled by the empty internal catch, because actually we have already handled the problem.

Related