Skip to main content
Home Forums Silverlight Programming Programming with .NET - General HttpWebRequest - receiving stream before it's completed. Should it work?
11 replies. Latest Post by Zhi Chen on April 23, 2009.
(0)
plafond444
Member
9 points
22 Posts
06-23-2008 1:42 PM |
...because it works on a .Net console application. On my console app, I receive data every 10 sec (see my httphandler code, it's just a loop with Thread.Sleep(10000)). But in my SL app, it all arrives after 50 sec (once completed).
Here is the code... Same method in both apps... except for the "Console.WriteLine(..."
public void DownloadTest(){ string url = "http://localhost:3583/_testerweb/test.clbk"; AutoResetEvent autoEvent = new AutoResetEvent(false); HttpWebRequest req = WebRequest.Create(url) as HttpWebRequest; req.BeginGetResponse(arResponse => { try { using (HttpWebResponse svrResp = req.EndGetResponse(arResponse) as HttpWebResponse) { using (StreamReader sr = new StreamReader(svrResp.GetResponseStream())) { String outputData = ""; int bsize = 256; Char[] buffer = new Char[bsize]; int nbByte = sr.Read(buffer, 0, bsize); while (nbByte > 0) { outputData = new String(buffer, 0, nbByte); Console.WriteLine(outputData); nbByte = sr.Read(buffer, 0, bsize); } } } } finally { autoEvent.Set(); } }, ""); autoEvent.WaitOne();
}
...and from the HttpHandler that writes to the string:
public void ProcessRequest(HttpContext context){ int nb = 5; while (nb > 0) { context.Response.Write("status : "+nb); context.Response.Flush(); nb--; Thread.Sleep(10000); } context.Response.Write("ALL DONE"); context.Response.End();}
It cannot be easier... Either it's a bug or it's a constraint on Silverlight version?
Thanks for your feebacks!
johnnystock
Contributor
2295 points
362 Posts
06-23-2008 1:53 PM |
Not a bug but a constraint in Silverlight. Silverlight is asynchronous only so it's basically all or nothing.
06-23-2008 2:43 PM |
Thanks John... Asynchronous, yes but still... do you mean the same kind of contraint as in Microsoft.XMLHTTP where readyState.INTERACTIVE is not working ? I mean Mozilla's XMLHttpRequest used in async mode can receive the stream before it's completed, why not HttpWebRequest?
pbromberg
2114 points
368 Posts
06-23-2008 3:52 PM |
What John means is that in Silverlight, WebClient and HttpWebRequest ONLY work in asynchronous mode. In order to get your results, you must do so inside the callback method.
06-23-2008 8:45 PM |
But if the asynchronous mode is the problem, why does it work in my console app? It's probably not the same assembly code (System.Net.dll), but since HttpWebRequest.BeginGetResponse's nature is to process the request asynchronously, shouldn't it produce the same result on both environments?
06-23-2008 9:28 PM |
No. HttpWebRequest or WebClient implementations in the Silverlight CLR are NOT the exact equivalents of the full .NET Framework implementations.
You have to remember, when you create a Silverlight application you are compiling your code against the Silverlight CLR, which is a subset of the .NET Framework that is designed to install and run on the client, in the web browser, on the client machine. These classes have been created to work *like* their full framework counterparts, but to run in the Silverlight framework which is designed to download, install, and run on the client in the browser itself.
In other words, there is no such thing as a "Console App" in Silverlight.
Ola Karl...
127 points
25 Posts
06-24-2008 1:11 AM |
There's actually new functionality in Beta 2 which might do something along the lines of what you're after.
From the HttpWebRequest.AllowReadStreamBuffering Property documentation
"When AllowReadStreamBuffering is true, the data is buffered in memory so it is ready to be read by the application.
The AllowReadStreamBuffering property affects when the callback from BeginGetResponse method is called. When the AllowReadStreamBuffering property is true, the callback is raised once the entire stream has been downloaded into memory. When the AllowReadStreamBuffering property is false, the callback is raised as soon as the stream is available for reading which may be before all data has arrived."
06-24-2008 5:26 AM |
I never said I was running a Silverlight console app.... I have one web project for my httphandler, one "console app" project (full framework) and one Silverlight project. I just use the exact same DownloadTest() method (see the original post) in both projects.
As far as I know, the only implementation difference using HttpWebRequest (full vs SL) was a threading issue (running on UI thread), not an asynchronous one.
06-24-2008 5:41 AM |
Thanks Ola, exactly what I thought when I found AllowReadStreamBuffering yesterday... I was going to reply to my own thread... but unfortunately, it doesn't seem to affect anything. I set it to "false" just before the req.BeginGetResponse(... call.
As you mentioned, it should allow the stream to be readable right after BeginGetResponse... as the "full framework" one does (by default).
Does someone has a working example with HttpWebRequest.AllowReadStreamBuffering set to false?
Thanks
06-26-2008 5:40 AM |
Yes, it does work! (...but I still don't know if it's a bug or "by design")So, what was wrong with my initial sample code? The first difference between the full framework and SL when calling BeginGetResponse is AllowReadStreamBuffering. As mentioned by Ola, HttpWebRequest.AllowReadStreamBuffering (new in Beta 2) needs to be set to false (default is true). That will work but there is a catch (the second difference between "full framework" and Silverlight for BeginGetResponse). Why was it waiting until the end of the stream to step in BeginGetResponse then? 4kb...(4096 I suppose).HttpWebRequest.AllowReadStreamBuffering set BrowserHttpWebRequest._allowBufering variable. This is used in Completed, Failed and Progress methods.... Progress is the one.... if _allowBuffering==true, call the Callback param... and this event is raised by InternalWebRequest object... nothing I can get more from there... I haven't been able to find where, but I suppose that before Progress can be called, there is a conditional statement that verifies that the stream is greater then 4kb....So in my sample code, I was writing 5 times "status : XX" to the response stream (and was getting the result as one string instead of five small strings). The resulting string was far from 4kb (but this works in my app console).... If I send a 4kb chunk first, then the following "status : XX" are received every 10 sec as expected.Obviously, sending an initial 4kb chunk is applicable only when you control the server part... at least now you know that you will need to have received 4kb from the server before AllowReadStreamBuffering take effect.Cheers!
cagdasge...
11 points
23 Posts
09-17-2008 1:34 PM |
Thanks for this great information. I was looking for a way to read I made a couple of posts but nobody seemed to know about this feature. Thanks for pointing out "gotchas" too on your web page. http://blog.lfdx.com/blogengine.net/post/HttpWebRequestAllowReadStreamBuffering3dfalse-Still-buffering-up-to-4kb!.aspx According to my tests, this is true for Firefox 2, 3, and IE 6,7. I would like to add that according to my experiments the first message you send is not received until the second messsage is received unless the first message size is 8KB or bigger. This is true for both Firefox and IE.
Zhi Chen
4 points
2 Posts
04-23-2009 1:47 AM |
I think platond444's reply is great - very informative!!
I just discovered the initial buffering even I have the AllowReadStreamBuffering set to false.
Is there any way to disable the initial buffering. In my case I have the control over the server piece but writing 4K dummy data seems dum.
thanks