Home All Groups Group Topic Archive Search About

Async web calls can't be timed?

Author
2 Jan 2007 7:16 PM
Andy
Tough asynchronous web request question.

I'm making few asynchronous web requests (loop) using System.Net namespace
with
HttpWebRequest, BeginGetRespons, AsyncCallback and all that stuff. 

The asynchronous part works, but I also want to time my requests.  That part
does not work.
Someone suggested this:

ThreadPool.RegisterWaitForSingleObject(asyncResult.AsyncWaitHandle, new
WaitOrTimerCallback(ScanTimeoutCallback), requestState, (4 * 1000), true);

The above line times all my calls as one.  I want to be able to time every
request individually and if one of them is timing out, abort that one only.
There are no examples for this anywhere.  How do you time each individual
request on a specific thread.

Thanks in advance,

Author
2 Jan 2007 8:23 PM
Henning Krause [MVP - Exchange]
Hello,

well, with each call to BeginXXX, you get a unique IAsyncResult. And thus,
you can register each IAsyncResult.AsyncWaitHandle with
ThreadPool.RegisterWaitForSingleObject).

Where exactly is the problem here?

Best regards,
Henning Krause


Show quote
"Andy" <A***@discussions.microsoft.com> wrote in message
news:CB4C1CF3-E7ED-4077-A93A-F5092F3E4B79@microsoft.com...
> Tough asynchronous web request question.
>
> I'm making few asynchronous web requests (loop) using System.Net namespace
> with
> HttpWebRequest, BeginGetRespons, AsyncCallback and all that stuff.
>
> The asynchronous part works, but I also want to time my requests.  That
> part
> does not work.
> Someone suggested this:
>
> ThreadPool.RegisterWaitForSingleObject(asyncResult.AsyncWaitHandle, new
> WaitOrTimerCallback(ScanTimeoutCallback), requestState, (4 * 1000), true);
>
> The above line times all my calls as one.  I want to be able to time every
> request individually and if one of them is timing out, abort that one
> only.
> There are no examples for this anywhere.  How do you time each individual
> request on a specific thread.
>
> Thanks in advance,
>
>
Author
2 Jan 2007 10:25 PM
Andy
Show quote
"Henning Krause [MVP - Exchange]" wrote:

> Hello,
>
> well, with each call to BeginXXX, you get a unique IAsyncResult. And thus,
> you can register each IAsyncResult.AsyncWaitHandle with
> ThreadPool.RegisterWaitForSingleObject).
>
> Where exactly is the problem here?
>
> Best regards,
> Henning Krause
>
>
> "Andy" <A***@discussions.microsoft.com> wrote in message
> news:CB4C1CF3-E7ED-4077-A93A-F5092F3E4B79@microsoft.com...
> > Tough asynchronous web request question.
> >
> > I'm making few asynchronous web requests (loop) using System.Net namespace
> > with
> > HttpWebRequest, BeginGetRespons, AsyncCallback and all that stuff.
> >
> > The asynchronous part works, but I also want to time my requests.  That
> > part
> > does not work.
> > Someone suggested this:
> >
> > ThreadPool.RegisterWaitForSingleObject(asyncResult.AsyncWaitHandle, new
> > WaitOrTimerCallback(ScanTimeoutCallback), requestState, (4 * 1000), true);
> >
> > The above line times all my calls as one.  I want to be able to time every
> > request individually and if one of them is timing out, abort that one
> > only.
> > There are no examples for this anywhere.  How do you time each individual
> > request on a specific thread.
> >
> > Thanks in advance,
> >
> >
>
>

This is what I do:

            foreach(Uri uri in arrayList)
            {
                request = (HttpWebRequest)WebRequest.Create(uri);
                request.Method = "GET";

                data = new object();

                RequestState requestState = new RequestState(request, data, uri);
                asyncResult = request.BeginGetResponse(new
AsyncCallback(ProcessRequest), requestState);
                ThreadPool.RegisterWaitForSingleObject(asyncResult.AsyncWaitHandle, new
WaitOrTimerCallback(ScanTimeoutCallback), requestState, (30 * 1000), true);
            }

This should create a timer call back for each request, but it does not.  It
basically times all the requests together.  For example: if by the 3rd
request the timer is at 30 sec it times out.  I want every request to run for
30 sec max and time out as oppose to run till the timeout expires for all.
Author
2 Jan 2007 11:14 PM
Henning Krause [MVP - Exchange]
Hmm... should work this way.

But I usually only use one callback:

asyncResult = request.BeginGetResponse(new
null, null);
RequestState requestState = new RequestState(request, data, uri,
asyncResult);
ThreadPool.RegisterWaitForSingleObject(asyncResult.AsyncWaitHandle, new
WaitOrTimerCallback(ProcessRequest), requestState, (30 * 1000), true);

private void ProcessRequest(object state, bool timedOut) {
    RequestState data = state as RequestState;

    if (timedOut) {
      // Handle timeout
       data.Request.Abort();
    }
    else {
        HttpWebResponse response =
data.Request.EndGetResponse(data.AsyncResult);

        ProcessResponse(response);
    }

}

Best regards,
Henning Krause


Show quote
"Andy" <A***@discussions.microsoft.com> wrote in message
news:7CF9C1E2-3CB8-44A3-83C2-E579577E0DCC@microsoft.com...
>
>
> "Henning Krause [MVP - Exchange]" wrote:
>
>> Hello,
>>
>> well, with each call to BeginXXX, you get a unique IAsyncResult. And
>> thus,
>> you can register each IAsyncResult.AsyncWaitHandle with
>> ThreadPool.RegisterWaitForSingleObject).
>>
>> Where exactly is the problem here?
>>
>> Best regards,
>> Henning Krause
>>
>>
>> "Andy" <A***@discussions.microsoft.com> wrote in message
>> news:CB4C1CF3-E7ED-4077-A93A-F5092F3E4B79@microsoft.com...
>> > Tough asynchronous web request question.
>> >
>> > I'm making few asynchronous web requests (loop) using System.Net
>> > namespace
>> > with
>> > HttpWebRequest, BeginGetRespons, AsyncCallback and all that stuff.
>> >
>> > The asynchronous part works, but I also want to time my requests.  That
>> > part
>> > does not work.
>> > Someone suggested this:
>> >
>> > ThreadPool.RegisterWaitForSingleObject(asyncResult.AsyncWaitHandle, new
>> > WaitOrTimerCallback(ScanTimeoutCallback), requestState, (4 * 1000),
>> > true);
>> >
>> > The above line times all my calls as one.  I want to be able to time
>> > every
>> > request individually and if one of them is timing out, abort that one
>> > only.
>> > There are no examples for this anywhere.  How do you time each
>> > individual
>> > request on a specific thread.
>> >
>> > Thanks in advance,
>> >
>> >
>>
>>
>
> This is what I do:
>
> foreach(Uri uri in arrayList)
> {
> request = (HttpWebRequest)WebRequest.Create(uri);
> request.Method = "GET";
>
> data = new object();
>
> RequestState requestState = new RequestState(request, data, uri);
> asyncResult = request.BeginGetResponse(new
> AsyncCallback(ProcessRequest), requestState);
> ThreadPool.RegisterWaitForSingleObject(asyncResult.AsyncWaitHandle, new
> WaitOrTimerCallback(ScanTimeoutCallback), requestState, (30 * 1000),
> true);
> }
>
> This should create a timer call back for each request, but it does not.
> It
> basically times all the requests together.  For example: if by the 3rd
> request the timer is at 30 sec it times out.  I want every request to run
> for
> 30 sec max and time out as oppose to run till the timeout expires for all.
Author
3 Jan 2007 1:19 AM
Andy
Show quote
"Henning Krause [MVP - Exchange]" wrote:

> Hmm... should work this way.
>
> But I usually only use one callback:
>
> asyncResult = request.BeginGetResponse(new
> null, null);
> RequestState requestState = new RequestState(request, data, uri,
> asyncResult);
> ThreadPool.RegisterWaitForSingleObject(asyncResult.AsyncWaitHandle, new
> WaitOrTimerCallback(ProcessRequest), requestState, (30 * 1000), true);
>
> private void ProcessRequest(object state, bool timedOut) {
>     RequestState data = state as RequestState;
>
>     if (timedOut) {
>       // Handle timeout
>        data.Request.Abort();
>     }
>     else {
>         HttpWebResponse response =
> data.Request.EndGetResponse(data.AsyncResult);
>
>         ProcessResponse(response);
>     }
>
> }
>
> Best regards,
> Henning Krause
>
>
> "Andy" <A***@discussions.microsoft.com> wrote in message
> news:7CF9C1E2-3CB8-44A3-83C2-E579577E0DCC@microsoft.com...
> >
> >
> > "Henning Krause [MVP - Exchange]" wrote:
> >
> >> Hello,
> >>
> >> well, with each call to BeginXXX, you get a unique IAsyncResult. And
> >> thus,
> >> you can register each IAsyncResult.AsyncWaitHandle with
> >> ThreadPool.RegisterWaitForSingleObject).
> >>
> >> Where exactly is the problem here?
> >>
> >> Best regards,
> >> Henning Krause
> >>
> >>
> >> "Andy" <A***@discussions.microsoft.com> wrote in message
> >> news:CB4C1CF3-E7ED-4077-A93A-F5092F3E4B79@microsoft.com...
> >> > Tough asynchronous web request question.
> >> >
> >> > I'm making few asynchronous web requests (loop) using System.Net
> >> > namespace
> >> > with
> >> > HttpWebRequest, BeginGetRespons, AsyncCallback and all that stuff.
> >> >
> >> > The asynchronous part works, but I also want to time my requests.  That
> >> > part
> >> > does not work.
> >> > Someone suggested this:
> >> >
> >> > ThreadPool.RegisterWaitForSingleObject(asyncResult.AsyncWaitHandle, new
> >> > WaitOrTimerCallback(ScanTimeoutCallback), requestState, (4 * 1000),
> >> > true);
> >> >
> >> > The above line times all my calls as one.  I want to be able to time
> >> > every
> >> > request individually and if one of them is timing out, abort that one
> >> > only.
> >> > There are no examples for this anywhere.  How do you time each
> >> > individual
> >> > request on a specific thread.
> >> >
> >> > Thanks in advance,
> >> >
> >> >
> >>
> >>
> >
> > This is what I do:
> >
> > foreach(Uri uri in arrayList)
> > {
> > request = (HttpWebRequest)WebRequest.Create(uri);
> > request.Method = "GET";
> >
> > data = new object();
> >
> > RequestState requestState = new RequestState(request, data, uri);
> > asyncResult = request.BeginGetResponse(new
> > AsyncCallback(ProcessRequest), requestState);
> > ThreadPool.RegisterWaitForSingleObject(asyncResult.AsyncWaitHandle, new
> > WaitOrTimerCallback(ScanTimeoutCallback), requestState, (30 * 1000),
> > true);
> > }
> >
> > This should create a timer call back for each request, but it does not.
> > It
> > basically times all the requests together.  For example: if by the 3rd
> > request the timer is at 30 sec it times out.  I want every request to run
> > for
> > 30 sec max and time out as oppose to run till the timeout expires for all.
>
> Well if you use one call only it is obvious it times only that call.  Try adding more than one call.  The timer spans across all threads and times them as a whole.
Author
3 Jan 2007 5:21 PM
Chris Mullins [MVP]
"Andy" <A***@discussions.microsoft.com> wrote
>
> I'm making few asynchronous web requests (loop) using System.Net namespace
> with
> HttpWebRequest, BeginGetRespons, AsyncCallback and all that stuff.
>
> The asynchronous part works, but I also want to time my requests.

I would grab the current system time (DateTime.Now), and just pass that in
as state to the async call.

When you get your callback, you can then (inside the callback) access your
original start time by saying
"DateTime startTime = ar.AsyncState as DateTime;"

From here, it's easy enough to calculate a start date.

--
Chris Mullins, MCSD.NET, MCPD:Enterprise, MVP C#
http://www.coversant.net/blogs/cmullins
Author
3 Jan 2007 8:41 PM
Andy
Show quote
"Chris Mullins [MVP]" wrote:

> "Andy" <A***@discussions.microsoft.com> wrote
> >
> > I'm making few asynchronous web requests (loop) using System.Net namespace
> > with
> > HttpWebRequest, BeginGetRespons, AsyncCallback and all that stuff.
> >
> > The asynchronous part works, but I also want to time my requests.
>
> I would grab the current system time (DateTime.Now), and just pass that in
> as state to the async call.
>
> When you get your callback, you can then (inside the callback) access your
> original start time by saying
> "DateTime startTime = ar.AsyncState as DateTime;"
>
> From here, it's easy enough to calculate a start date.
>
> --
> Chris Mullins, MCSD.NET, MCPD:Enterprise, MVP C#
> http://www.coversant.net/blogs/cmullins
>
>
>
Hm.. So wait, you are saying I can set the time in the state object and pass
it to my call.  When the callback gets triggered I can check the time again
and see the difference.  That's great, but I wanted to set a timeout.  I did
not want to time the call only.  I see your point, but that's half the
equation.  How do I call a callback from the async call if the async call is
taking more than 10 sec for example.
Author
3 Jan 2007 8:58 PM
Henning Krause [MVP - Exchange]
And the problem here is, that async calls don't automatically timeout, as
synchronous do...
So, the call can take forever to complete...

Best regards,
Henning Krause

Show quote
"Andy" <A***@discussions.microsoft.com> wrote in message
news:4985AF61-01C5-48B6-8A04-D178F1DFC707@microsoft.com...
>
>
> "Chris Mullins [MVP]" wrote:
>
>> "Andy" <A***@discussions.microsoft.com> wrote
>> >
>> > I'm making few asynchronous web requests (loop) using System.Net
>> > namespace
>> > with
>> > HttpWebRequest, BeginGetRespons, AsyncCallback and all that stuff.
>> >
>> > The asynchronous part works, but I also want to time my requests.
>>
>> I would grab the current system time (DateTime.Now), and just pass that
>> in
>> as state to the async call.
>>
>> When you get your callback, you can then (inside the callback) access
>> your
>> original start time by saying
>> "DateTime startTime = ar.AsyncState as DateTime;"
>>
>> From here, it's easy enough to calculate a start date.
>>
>> --
>> Chris Mullins, MCSD.NET, MCPD:Enterprise, MVP C#
>> http://www.coversant.net/blogs/cmullins
>>
>>
>>
> Hm.. So wait, you are saying I can set the time in the state object and
> pass
> it to my call.  When the callback gets triggered I can check the time
> again
> and see the difference.  That's great, but I wanted to set a timeout.  I
> did
> not want to time the call only.  I see your point, but that's half the
> equation.  How do I call a callback from the async call if the async call
> is
> taking more than 10 sec for example.
Author
4 Jan 2007 4:41 PM
Chris Mullins [MVP]
You really can't have the async calls timeout, unfortunatly.

I agree with you that this isn't exactly ideal. In general, to abort an
async operation, you've got to dispose the object the operation is occuring
on.

For example, to abort a socket.BeginRead call, I've got to dispose the
socket. As soon as that socket it disposed, my callback will fire, call
EndRead, and pickup that the socket has been closed.

--
Chris Mullins, MCSD.NET, MCPD:Enterprise, MVP C#
http://www.coversant.net/blogs/cmullins

Show quote
"Andy" <A***@discussions.microsoft.com> wrote in message
news:4985AF61-01C5-48B6-8A04-D178F1DFC707@microsoft.com...
>
>
> "Chris Mullins [MVP]" wrote:
>
>> "Andy" <A***@discussions.microsoft.com> wrote
>> >
>> > I'm making few asynchronous web requests (loop) using System.Net
>> > namespace
>> > with
>> > HttpWebRequest, BeginGetRespons, AsyncCallback and all that stuff.
>> >
>> > The asynchronous part works, but I also want to time my requests.
>>
>> I would grab the current system time (DateTime.Now), and just pass that
>> in
>> as state to the async call.
>>
>> When you get your callback, you can then (inside the callback) access
>> your
>> original start time by saying
>> "DateTime startTime = ar.AsyncState as DateTime;"
>>
>> From here, it's easy enough to calculate a start date.
>>
>> --
>> Chris Mullins, MCSD.NET, MCPD:Enterprise, MVP C#
>> http://www.coversant.net/blogs/cmullins
>>
>>
>>
> Hm.. So wait, you are saying I can set the time in the state object and
> pass
> it to my call.  When the callback gets triggered I can check the time
> again
> and see the difference.  That's great, but I wanted to set a timeout.  I
> did
> not want to time the call only.  I see your point, but that's half the
> equation.  How do I call a callback from the async call if the async call
> is
> taking more than 10 sec for example.
Author
4 Jan 2007 6:41 PM
Henning Krause [MVP - Exchange]
Well,

the HttpWebRequest class has an Abort method..

Best regards,
Henning Krause

Show quote
"Chris Mullins [MVP]" <cmull***@yahoo.com> wrote in message
news:ugyzq8BMHHA.4848@TK2MSFTNGP04.phx.gbl...
> You really can't have the async calls timeout, unfortunatly.
>
> I agree with you that this isn't exactly ideal. In general, to abort an
> async operation, you've got to dispose the object the operation is
> occuring on.
>
> For example, to abort a socket.BeginRead call, I've got to dispose the
> socket. As soon as that socket it disposed, my callback will fire, call
> EndRead, and pickup that the socket has been closed.
>
> --
> Chris Mullins, MCSD.NET, MCPD:Enterprise, MVP C#
> http://www.coversant.net/blogs/cmullins
>
> "Andy" <A***@discussions.microsoft.com> wrote in message
> news:4985AF61-01C5-48B6-8A04-D178F1DFC707@microsoft.com...
>>
>>
>> "Chris Mullins [MVP]" wrote:
>>
>>> "Andy" <A***@discussions.microsoft.com> wrote
>>> >
>>> > I'm making few asynchronous web requests (loop) using System.Net
>>> > namespace
>>> > with
>>> > HttpWebRequest, BeginGetRespons, AsyncCallback and all that stuff.
>>> >
>>> > The asynchronous part works, but I also want to time my requests.
>>>
>>> I would grab the current system time (DateTime.Now), and just pass that
>>> in
>>> as state to the async call.
>>>
>>> When you get your callback, you can then (inside the callback) access
>>> your
>>> original start time by saying
>>> "DateTime startTime = ar.AsyncState as DateTime;"
>>>
>>> From here, it's easy enough to calculate a start date.
>>>
>>> --
>>> Chris Mullins, MCSD.NET, MCPD:Enterprise, MVP C#
>>> http://www.coversant.net/blogs/cmullins
>>>
>>>
>>>
>> Hm.. So wait, you are saying I can set the time in the state object and
>> pass
>> it to my call.  When the callback gets triggered I can check the time
>> again
>> and see the difference.  That's great, but I wanted to set a timeout.  I
>> did
>> not want to time the call only.  I see your point, but that's half the
>> equation.  How do I call a callback from the async call if the async call
>> is
>> taking more than 10 sec for example.
>
>

AddThis Social Bookmark Button