WebRequest times out...but only 3rd time and on...

T

Tim Cowan

Hi,

I put this code in a windows forms app for testing. The IP values are both
correct. It works the first time, the second time but at the third time it
fails with timeout... I have it running here AND in a service with a 30
minute interval.

1. Am I doing this correclty? Is there a better way to go to a URI and pass
a couple of variables?

2. If I am doing this correctly any idea why it would be timing out on the
third time onwards? The ASP page just takes the values and writes them to a
DB. If I run it in a browser I can run it over and over with no timeouts...I
think it must be something that I am doing but I can't thing what.

Can someone help?

Tim

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
namespace WindowsApplication2
{
public partial class Form1 : Form
{
static System.Timers.Timer timer = new System.Timers.Timer(5000);
public Form1()
{
InitializeComponent();
timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed);
timer.Start();
}
static void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
timer.Stop();
Console.WriteLine("Timer Elapsed");
System.Net.WebRequest req =
System.Net.WebRequest.Create(http://24.36.xxx.xxx/server/update_ip.asp?storeid=271716723&ipaddress=67.70.xxx.xxx);

req.GetResponse();
Console.WriteLine("Done");
Console.WriteLine();
timer.Start();
}
}
}
 
J

Jon Skeet [C# MVP]

Tim said:
I put this code in a windows forms app for testing. The IP values are both
correct. It works the first time, the second time but at the third time it
fails with timeout... I have it running here AND in a service with a 30
minute interval.

1. Am I doing this correclty? Is there a better way to go to a URI and pass
a couple of variables?

I don't have time to look at the rest of your code in detail at the
minute, but I believe the problem is that you're not disposing of the
WebResponse. If you do, you should notice everything being fine. .NET
is happy to have two connections up at a time, but your existing
responses are "hogging" the connections it's made.

Jon
 
T

Tim Cowan

Thanks Jon, that was it. As I wasn't putting it into a reponse object I
couldn't see it, but now it works great.
System.Net.WebResponse resp = req.GetResponse();
resp.Close();
 
J

Jon Skeet [C# MVP]

Tim Cowan said:
Thanks Jon, that was it. As I wasn't putting it into a reponse object I
couldn't see it, but now it works great.
System.Net.WebResponse resp = req.GetResponse();
resp.Close();

A generally better approach would be:

using (WebResponse resp = req.GetResponse())
{
// Anything else here
}

That way the response will be disposed even if an exception is thrown.
 
M

matt_felzani

jon

if you have a minute, can you comment on when the code should be as
you have it above and when it should be:

using (WebResponse resp = req.GetResponse())
{
// Anything else here


GC.KeepAlive(resp); <---------
}

it was my understanding that the 'using' statement expanded to
something like:

try{
// the code
}
finally
{
theObjectInTheUsing.Dispose();
}

thus the GC.KeepAlive() seems unnecessary since the object shouldn't be
collected until after the finally block. is it for the scenario that
the object doesn't implement IDisposable's Dispose()?

thanks in advance,
matt
 
T

Tim Cowan

Thanks Jon. I really appreciate it when someone helps me out by suggesting
a better way to code. I am always trying to write more 'elegant' and solid
code.

Thanks

Tim
 
J

Joerg Jooss

Thus wrote Tim,
Hi,

I put this code in a windows forms app for testing. The IP values are
both correct. It works the first time, the second time but at the
third time it fails with timeout... I have it running here AND in a
service with a 30 minute interval.

1. Am I doing this correclty? Is there a better way to go to a URI and
pass a couple of variables?

Has been answered :)
2. If I am doing this correctly any idea why it would be timing out on
the third time onwards? The ASP page just takes the values and writes
them to a DB. If I run it in a browser I can run it over and over with
no timeouts...I think it must be something that I am doing but I can't
thing what.

Because two is the number of persistent ("keep-alive") HTTP connections a
client should establish to one server according to the HTTP 1.1 spec (RFC
2616).

Your not-disposed-of responses actually block all underlying TCP connections
to the web server, until your code either times out or at least one response
has been finalized and disposed of.

Cheers,
 
J

Jon Skeet [C# MVP]

if you have a minute, can you comment on when the code should be as
you have it above and when it should be:

using (WebResponse resp = req.GetResponse())
{
// Anything else here


GC.KeepAlive(resp); <---------
}

You never need that KeepAlive, you're right. And if the type returned
by resp doesn't implement IDisposable, the statement won't compile in
the first place.
 
M

matt_felzani

that's what i was thinking, but a bit back i read this article on
theserverside.net:

http://www.theserverside.net/articles/showarticle.tss?id=GarbageCollection

which confused me as they say that it was the usage of GC.KeepAlive()
in a using block which solved their bug. however, could have been more
of a outlier-type scenario? they talk about having a 'proxy' as well
which is probably the root of the problem (not that the proxy *is* the
problem, per sa, but rather just part of the complicated equation) in
that the proxy and the 'real' object are disposed of as separate
entities as opposed to an atomic instance.

great catch on IDisposable. that was just silly on my part. oh well,
i'm past it now.

thanks again!
 
J

Jon Skeet [C# MVP]

that's what i was thinking, but a bit back i read this article on
theserverside.net:

http://www.theserverside.net/articles/showarticle.tss?id=GarbageCollection

which confused me as they say that it was the usage of GC.KeepAlive()
in a using block which solved their bug. however, could have been more
of a outlier-type scenario? they talk about having a 'proxy' as well
which is probably the root of the problem (not that the proxy *is* the
problem, per sa, but rather just part of the complicated equation) in
that the proxy and the 'real' object are disposed of as separate
entities as opposed to an atomic instance.

I strongly suspect that GC.KeepAlive wasn't actually what solved the
problem for them. It wouldn't be the first time I've seen someone apply
two changes at once and declare them both necessary, without having
tested each separately.

There are oddities with garbage collection to be sure, but none that
would do that, IMO.

Interestingly, they *do* have a bug in their Dispose implementation.
They set inst to 0 and don't use it any further in the method, but
that's *before* they call GC.SuppressFinalize. I suspect they may have
seen finalization taking place between the call to Interlocked.Exchange
and the call to SuppressFinalize, which would have caused them some
grief...

Anyway, I'd want to see clear evidence of the finalizer being called
within the using block before believing it.
great catch on IDisposable. that was just silly on my part. oh well,
i'm past it now.

:)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top