Set timeout for webClient.DownloadFile()
Try WebClient.DownloadFileAsync()
. You can call CancelAsync()
by timer with your own timeout.
How to change the timeout on a .NET WebClient object
You can extend the timeout: inherit the original WebClient class and override the webrequest getter to set your own timeout, like in the following example.
MyWebClient was a private class in my case:
private class MyWebClient : WebClient
{
protected override WebRequest GetWebRequest(Uri uri)
{
WebRequest w = base.GetWebRequest(uri);
w.Timeout = 20 * 60 * 1000;
return w;
}
}
Can't implement timeout when trying to download a file using WebClient.DownloadFile() or WebRequest
The timeout you implemented concerns getting Response, but not ResponseStream which contains all the data and takes usually more time to achieve. For example getting response usually takes below 1 second, but downloading content of a web page could take few seconds.
As for downloading files, you can use HttpWebRequest
to get HttpWebResponse
and from it use method GetResponseStream()
to get the stream to the data.
This will be helpful:
Encoding trouble with HttpWebResponse
Especially the part where byte[] buffer
is used to get parts of data instead of StreamReader
ReadToEnd()
method. While downloading parts of data to buffer you may check current DateTime against the timeout DateTime and thus allow cancelling the download after it.
Edit: a useful piece of code
private byte[] DownloadFile( string uri, int requestTimeout, int downloadTimeout, out bool isTimeout, out int bytesDownloaded )
{
HttpWebRequest request = WebRequest.Create( uri ) as HttpWebRequest;
request.Timeout = requestTimeout;
HttpWebResponse response = null;
Stream responseStream = null;
MemoryStream downloadedData = null;
byte[] result = null;
bytesDownloaded = 0;
isTimeout = false;
try
{
// Get response
response = request.GetResponse() as HttpWebResponse;
byte[] buffer = new byte[ 16384 ];
// Create buffer for downloaded data
downloadedData = new MemoryStream();
// Set the timeout
DateTime timeout = DateTime.Now.Add( new TimeSpan( 0, 0, 0, 0, downloadTimeout ) );
// Read parts of the stream
responseStream = response.GetResponseStream();
int bytesRead = 0;
DateTime now = DateTime.Now;
while ( (bytesRead = responseStream.Read( buffer, 0, buffer.Length )) > 0 && DateTime.Now < timeout )
{
downloadedData.Write( buffer, 0, bytesRead );
now = DateTime.Now;
bytesDownloaded += bytesRead;
}
// Notify if timeout occured (could've been written better)
if ( DateTime.Now >= timeout )
{
isTimeout = true;
}
}
catch ( WebException ex )
{
// Grab timeout exception
if ( ex.Status == WebExceptionStatus.Timeout )
{
isTimeout = true;
}
}
finally
{
// Close the stream
if ( responseStream != null )
{
responseStream.Close();
}
}
if ( downloadedData != null )
{
result = downloadedData.GetBuffer();
downloadedData.Close();
}
return result;
}
Usage
private void button1_Click( object sender, EventArgs e )
{
bool isTimeout;
int bytesDownloaded;
byte[] data = DownloadFile( something, 1000,500, out isTimeout, out bytesDownloaded );
MessageBox.Show( "Downloaded " + bytesDownloaded.ToString() + " bytes, Timeout = " + isTimeout.ToString() );
}
This code is still vulnerable for other exceptions you may encounter, bear that in mind.
Downloading file from url with timeout
You can create your own WebClient
public class MyWebClient : WebClient
{
protected override WebRequest GetWebRequest(Uri address)
{
var req = base.GetWebRequest(address);
req.Timeout = 15000;
return req;
}
}
How to implement a Timeout on WebClient.DownloadFileAsync
You can use WebClient.DownloadFileAsync(). Now inside a timer you can call CancelAsync() like so:
System.Timers.Timer aTimer = new System.Timers.Timer();
System.Timers.ElapsedEventHandler handler = null;
handler = ((sender, args)
=>
{
aTimer.Elapsed -= handler;
wc.CancelAsync();
});
aTimer.Elapsed += handler;
aTimer.Interval = 100000;
aTimer.Enabled = true;
Else create your own weclient
public class NewWebClient : WebClient
{
protected override WebRequest GetWebRequest(Uri address)
{
var req = base.GetWebRequest(address);
req.Timeout = 18000;
return req;
}
}
Set a timeout on webClient.DownloadData?
Looks like HttpWebRequest may be the way to go
Related Topics
The Name 'Controlname' Does Not Exist in the Current Context
Parallel.Foreach and Async-Await
Vb.Net Equivalent for C# 'Dynamic' with Option Strict On
Async/Await With/Without Awaiting (Fire and Forget)
How to Create a Dto in C# ASP.NET from a Fairly Complex JSON Response
Most Common C# Bitwise Operations on Enums
Interop Type Cannot Be Embedded
C# Linq Group by on Multiple Columns
Is the C# Static Constructor Thread Safe
Quickest Way to Compare Two Generic Lists for Differences
Combobox: Adding Text and Value to an Item (No Binding Source)
Easiest Way to Create a Cascade Dropdown in ASP.NET MVC 3 with C#
Password Protect a SQLite Db. Is It Possible
Convert Integer to Binary in C#
Send a File via Http Post with C#
How to Move Mouse Cursor Using C#
C# - Faster Alternatives to Setpixel and Getpixel for Bitmaps for Windows Forms App