4

Using a modified WebClient, I download data periodically from a service with the following characteristics:

  • The data download (~1GB) can take around 20 minutes
  • Sometimes the service decides not to return any data at all (request hangs), or takes minutes to hours to return the first byte.

I would like to fail fast in the event that the service does not return any data within a reasonable (configurable) amount of time, yet allow plenty of time for a download that is making progress to succeed.

It seems that the WebRequest.Timeout property controls the total time for the request to complete, while ReadWriteTimeout controls the total time available to read data once the data transfer begins.

Am I missing a property that would control the maximum amount of time to wait between establishing the connection and the first byte returning? If there is no such property, how can I approach the problem?

Community
  • 1
  • 1
Eric J.
  • 147,927
  • 63
  • 340
  • 553

1 Answers1

2

I am not aware of any additional timeout property that will achieve the result you are looking for. The first thought that comes to mind is attaching a handler to DownloadProgressChanged that will update a flag to indicate data has been received (not always accurate though).

Using a Timer or EventWaitHandle you could then block (or handle async if you prefer) for a short period of time and evaluate whether any data has been received. The code below is not a fully fleshed out example, but an idea of how it may be implemented.

using (var manualResetEvent = new ManualResetEvent(false))
using (var client = new WebClient())
{
    client.DownloadProgressChanged += (sender, e) => manualResetEvent.Set();
    client.DownloadDataAsync(new Uri("https://github.com/downloads/cbaxter/Harvester/Harvester.msi"));

    if (!manualResetEvent.WaitOne(5000))
        client.CancelAsync();
}

In the above example, the manualResetEvent.WaitOne will return true if DownloadProgressChanged was invoked. You will likely want to check e.BytesReceived > 0 and only set for non-zero values, but I think you get the idea?

Chris Baxter
  • 16,083
  • 9
  • 51
  • 72