Cancelling a file download using HttpWebRequest

J

Jeff Robichaud

Hi all,

I have some code running on the Pocket PC (w/CF v2.0) that grabs a file
(about 20 MB) from the server using HttpWebRequest. I want to give to user
the possibility to cancel the download (the download method is running in
another thread which is aborted when the user cancels).

From what I understand, to close everything gracefully requires calling
Abort() on the HttpWebRequest object and/or Close() on the WebResponse
object. Failure to do so will interfere in the subsequent attempts to
download the file.

But here goes, calling either of the methods seems to hang the device, but
in fact I think there is some cleanup going on in the backgroup. BUT, from a
user point of view, it changes nothing. Is there a bug in the CF because the
same code works A1 on the desktop.

Has anybody been able to work around this, or am I simply missing something?
Thanks.

Here's a lean version of the code:
private void DownloadFile()
{
HttpWebRequest request = null;
WebResponse response = null;
Stream stream = null;
FileStream fs = null;

try
{
request = (HttpWebRequest)WebRequest.Create(_remoteFileUrl);
request.KeepAlive = false;
response = request.GetResponse();
stream = response.GetResponseStream();

string localFilePath = Path.GetTempPath() +
Path.GetFileName(_remoteFileUrl);
fs = new FileStream(localFilePath, FileMode.Create);

int total = 0;
byte[] buffer = new byte[0x1000];

while (true)
{
int currentRead = stream.Read(buffer, 0, buffer.Length);
total += currentRead;
fs.Write(buffer, 0, currentRead);

if (currentRead == 0) { break; }
}
}
finally
{
fs.Close();
response.Close();
request.Abort();
}
}
 
G

Guest

One alternative is to place an is running property in the download class.
Then on your Abort method, set this property to false. In your download
method check for is running and and break from your while statement, then
allow your method to clean up as coded. Also in your abort, do a wait check.
If the method does not complete within your alloted time, then manually
close the request objects.

I hope this helps,
Regards,
Rick D.
Contractor
 
J

Jeff Robichaud

One alternative is to place an is running property in the download class.
Then on your Abort method, set this property to false.

Rick,

The Abort method is not mine, it's provided by the API (HttpWebRequest).
Neither HttpWebRequest.Abort() or WebResponse.Close() works, it seems like
the underlying stream is flushing and it takes about the same time as
letting the download go (or even more). So I'm thinking that there's no
point in cancelling, since for the user it doesn't save any time...

Thanks anyway :)

In your download
 
G

Guest

I assume that your FileDownload method is contained in some sort of class,
since you are writing C#. You would create an Abort method for your class
and then do the steps I mentioned above. Then in your Abort method you can
call Abort for the Web Request and WebResponse classes. I understand that
Abort is a method for these classes, but there is nothing in the C# standards
that says you can not write your OWN abort method for you OWN class.

Rick D.
Contractor
 
J

Jeff Robichaud

All right, when you say "then manually close the request objects", I suppose
you mean calling response.Close() ? This is actually the call that hangs, so
no matter how much code I would put around this, it still wouldn't work. So
my question was to see if someone had already seen this...maybe it's the CF
(because it works on Windows) or maybe juste the device, I'm still looking
for an answer.

Best Regards.
 
G

Guest

You alter your while loop to look like this:

while (bRunning)
{
int currentRead = stream.Read(buffer, 0, buffer.Length);
total += currentRead;
fs.Write(buffer, 0, currentRead);

if (currentRead == 0) { break; }
}

then in your class abort method you set bRunning = false. this allows the
while loop to terminate following the next read. You will then allow your
method to fall through and do its cleanup.

Regards,
Rick D.
Contractor
 
G

Guest

Here is an example of the Abort method I use

/// <summary>
/// Stops the running download thread
/// </summary>
public void StopDownload()
{
int threadStopCount = 0;
bRunning = false;

// Continue to wait until the read thread terminates
while (bThreadRunning)
{
threadStopCount++;

Thread.Sleep(500);

// If the wait thread has waited longer than 10 seconds,
then terminate it
if (threadStopCount >= 20)
{
readThread.Abort();
break;
}
}

// Aborts the current web request
webRequest.Abort();
}

Where readThread is the System.Threading.Thread object for the download
bThreadRunning is a boolean that is set to true when we start the thread and
false when the thread terminates. This method waits 10 seconds before
aborting the thread. and bRunning is the boolean that is in your while loop

while(bRunning) instead of while(true)

I hope this helps.

Regards,
Rick D.
Contractor
 
H

Hilton

It is a really bad CF bug. Closing the download cause the file to continue
to be downloaded and the close only happens at the end; i.e. your device is
not hanging, it is still download the 20MB. There are many ways to verify
this; e.g. watch the DSL activity light, wait the time it takes for the 20MB
file to downlaod and magically the Close() will terminate, watch the file
size grow...

Please try this and report back.

Thanks,

Hilton
 
G

Guest

Not sure I'd consider the "DSL light" to be any definitive form of
diagnostic - Wireshark would tell you for sure (and for free).

It does sound sound a bit fishy though.


--

Chris Tacke, eMVP
Join the Embedded Developer Community
http://community.opennetcf.com


Hilton said:
It is a really bad CF bug. Closing the download cause the file to
continue to be downloaded and the close only happens at the end; i.e. your
device is not hanging, it is still download the 20MB. There are many ways
to verify this; e.g. watch the DSL activity light, wait the time it takes
for the 20MB file to downlaod and magically the Close() will terminate,
watch the file size grow...

Please try this and report back.

Thanks,

Hilton


Jeff Robichaud said:
Hi all,

I have some code running on the Pocket PC (w/CF v2.0) that grabs a file
(about 20 MB) from the server using HttpWebRequest. I want to give to
user the possibility to cancel the download (the download method is
running in another thread which is aborted when the user cancels).

From what I understand, to close everything gracefully requires calling
Abort() on the HttpWebRequest object and/or Close() on the WebResponse
object. Failure to do so will interfere in the subsequent attempts to
download the file.

But here goes, calling either of the methods seems to hang the device,
but in fact I think there is some cleanup going on in the backgroup. BUT,
from a user point of view, it changes nothing. Is there a bug in the CF
because the same code works A1 on the desktop.

Has anybody been able to work around this, or am I simply missing
something? Thanks.

Here's a lean version of the code:
private void DownloadFile()
{
HttpWebRequest request = null;
WebResponse response = null;
Stream stream = null;
FileStream fs = null;

try
{
request = (HttpWebRequest)WebRequest.Create(_remoteFileUrl);
request.KeepAlive = false;
response = request.GetResponse();
stream = response.GetResponseStream();

string localFilePath = Path.GetTempPath() +
Path.GetFileName(_remoteFileUrl);
fs = new FileStream(localFilePath, FileMode.Create);

int total = 0;
byte[] buffer = new byte[0x1000];

while (true)
{
int currentRead = stream.Read(buffer, 0, buffer.Length);
total += currentRead;
fs.Write(buffer, 0, currentRead);

if (currentRead == 0) { break; }
}
}
finally
{
fs.Close();
response.Close();
request.Abort();
}
}
 
H

Hilton

Chris,
Not sure I'd consider the "DSL light" to be any definitive form of
diagnostic - Wireshark would tell you for sure (and for free).

Reminds me of the story about NASA spending millions to develop a pen that
would write in zero-G (and perhaps in a vacuum (I forget)). The Russians
used a pencil. :) Anyone know if this is true or not?

Seriously though, if the computer doesn't have any/much network activity and
you tap on Download, then the activity light flashes rapidly, then you tap
stop, but the light keeps flashing and the call does not return... Then
after about the same amount of time that the download should have taken, the
call returns and the activity light stops flashing... you can deduce a lot.
That's how I figured what was going on and I didn't have to install more
stuff on my machine. Now, before anyone jumps all over me, use whatever you
want, as crude as it seems the DSL activity light is just another simple
tool that might be useful.

It does sound sound a bit fishy though.

Yeah, the behavior is completely different on the Full versus CF Framework.
The desktop version works as advertised. The CF version definitely has (or
had) this bug. It may have been fixed by now, but since I write for CF 1, I
haven't tried it for a while and my code is not subject to that problem
anymore so I wouldn't know. It is pretty easy to test though.

Hilton
 
P

Paul G. Tobey [eMVP]

Of course, if you break off the lead in your pencil in zero G, you now have
a projectile floating around, so there's always plusses and minuses.
Certainly the pen story for NASA is true; not sure about the other half...

Paul T.
 

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