How to implement a Timeout on WebClient.DownloadFileAsync

我只是一个虾纸丫 提交于 2019-12-04 15:28:47
Jerin

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;
        }
    } 

Create a WebClientAsync class that implements the timer in the constructor. This way you aren't copying and pasting the timer code into every implementation.

public class WebClientAsync : WebClient
{
    private int _timeoutMilliseconds;

    public EdmapWebClientAsync(int timeoutSeconds)
    {
        _timeoutMilliseconds = timeoutSeconds * 1000;

        Timer timer = new Timer(_timeoutMilliseconds);
        ElapsedEventHandler handler = null;

        handler = ((sender, args) =>
        {
            timer.Elapsed -= handler;
            this.CancelAsync();
        });

        timer.Elapsed += handler;
        timer.Enabled = true;
    }

    protected override WebRequest GetWebRequest(Uri address)
    {
        WebRequest request = base.GetWebRequest(address);
        request.Timeout = _timeoutMilliseconds;
        ((HttpWebRequest)request).ReadWriteTimeout = _timeoutMilliseconds;

        return request;
    }



    protected override voidOnDownloadProgressChanged(DownloadProgressChangedEventArgs e)
    {
        base.OnDownloadProgressChanged(e);
        timer.Reset(); //If this does not work try below
        timer.Start();
    }
}

This will allow you to timeout if you lose Internet connection while downloading a file.

Here is another implementation, I tried to avoid any shared class/object variables to avoid trouble with multiple calls:

 public Task<string> DownloadFile(Uri url)
        {
            var tcs = new TaskCompletionSource<string>();
            Task.Run(async () =>
            {
                bool hasProgresChanged = false;
                var timer = new Timer(new TimeSpan(0, 0, 20).TotalMilliseconds);
                var client = new WebClient();

                void downloadHandler(object s, DownloadProgressChangedEventArgs e) => hasProgresChanged = true;
                void timerHandler(object s, ElapsedEventArgs e)
                {
                    timer.Stop();
                    if (hasProgresChanged)
                    {
                        timer.Start();
                        hasProgresChanged = false;
                    }
                    else
                    {
                        CleanResources();
                        tcs.TrySetException(new TimeoutException("Download timedout"));
                    }
                }
                void CleanResources()
                {
                    client.DownloadProgressChanged -= downloadHandler;
                    client.Dispose();
                    timer.Elapsed -= timerHandler;
                    timer.Dispose();
                }

                string filePath = Path.Combine(Path.GetTempPath(), Path.GetFileName(url.ToString()));
                try
                {
                    client.DownloadProgressChanged += downloadHandler;
                    timer.Elapsed += timerHandler;
                    timer.Start();
                    await client.DownloadFileTaskAsync(url, filePath);
                }
                catch (Exception e)
                {
                    tcs.TrySetException(e);
                }
                finally
                {
                    CleanResources();
                }

                return tcs.TrySetResult(filePath);
            });

            return tcs.Task;
        }
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!