views:

257

answers:

1

I'm trying to figure out how this works exactly.

HttpWebRequest has a method BeginGetResponse which accepts as a parameter a ResponseCallback. Firstly, is this callback called immediately (in a new thread) or once it receives a response back from the server? Or is it the job of EndGetResponse to wait for the response?

Secondly, once you have the response, you can access the response stream immediately, but the stream doesn't contain the full page until it's completed downloading, hence BeginRead. However, I seem to be able to access all the headers immediately, through properties like HttpWebResponse.ContentLength. Does this mean that EndGetResponse doesn't complete until the headers are fully downloaded, or is it that when you call the ContentLength parameter it hangs for a bit until that header is received?

+3  A: 

The Begin* and End* pattern is always the same:

  • Pass in an AsyncCallback to Begin
  • Wait for the call of that callback (not immediate)
  • Call End* always in the callback
  • Check the success of the callback/IAsyncResult (Was it cancelled? Any exceptions/errors?)
  • Use the result from End* here..

The result in your case is a WebResponse instance, which contains the Headers. So I think it's safe to assume that that part of the response was already received: The WebResponse object has no async magic hidden in its properties. If you access the ContentLength it's just a regular property and the object doesn't know or care if you got it using a blocking or an asynchronous call.

Benjamin Podszun
So you think the ResponseCallback isn't called until the headers are downloaded? Fair enough. Do you know how to check if it was cancelled, or is the only way to check through the exception thrown by `EndGetResponse`?
Mark
Unless you implement a way to cancel this operation I wouldn't know how this particular method could be stopped - it runs as an operation on the ThreadPool and neither you nor the user can stop it now. The general pattern allows for a better cancellation mechanism though, by extending the contract. WebClient for example does that and allows you to subscribe to events that get an instance of AsyncCompletedEventArgs, which again provide a .Cancelled property. This is pure convenience stuff based on the pattern given above.
Benjamin Podszun
It can easily be stopped actually: `ThreadPool.RegisterWaitForSingleObject(asyncResult.AsyncWaitHandle, TimeoutCallback, conn, TimeOutInterval, true);` I suppose I could add my own `Cancelled` property while I'm at it. `WebClient` doesn't quite do what I want it to, so I'm rebuilding it to be a bit more flexible, and support multiple concurrent downloads.
Mark