【问题标题】:How can I make some try method to try downloading files each 20 seconds until the download was successful?我怎样才能做出一些尝试方法来尝试每 20 秒下载一次文件,直到下载成功?
【发布时间】:2018-12-06 23:13:57
【问题描述】:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Downloads
{
    class GenerateCountries
    {
        public static List<string> CountriesCodes = new List<string>();
        public static List<string> CountriesNames = new List<string>();

        private string CountriesHtmlAddress;
        private string CountriesHtmlFile;
        private StreamWriter CountriesFile;
        private WebClient Client;

        public void Init()
        {
            CountriesHtmlAddress = "http://sat24.com/en/?ir=true";
            CountriesFile = new StreamWriter(Path.Combine(Path.GetDirectoryName(Application.LocalUserAppDataPath), "Countries.txt"));
            CountriesHtmlFile = Path.Combine(Path.GetDirectoryName(Application.LocalUserAppDataPath), "Sat24.html");
        }

        public void ExtractCountires()
        {
            Client = new WebClient();
            Client.DownloadFile(CountriesHtmlAddress, CountriesHtmlFile);
            Client.Dispose();

            string tag1 = "<li><a href=\"/en/";
            string tag2 = "</a></li>";

            string s = System.IO.File.ReadAllText(CountriesHtmlFile);
            s = s.Substring(s.IndexOf(tag1));
            s = s.Substring(0, s.LastIndexOf(tag2) + tag2.ToCharArray().Length);
            s = s.Replace("\r", "").Replace("\n", "").Replace(" ", "");

            string[] parts = s.Split(new string[] { tag1, tag2 }, StringSplitOptions.RemoveEmptyEntries);
            string tag3 = "<li><ahref=\"/en/";

            for (int i = 0; i < parts.Length; i++)
            {
                if (i == 40)
                {
                    break;
                }
                string l = "";
                if (parts[i].Contains(tag3))
                    l = parts[i].Replace(tag3, "");

                string z1 = l.Substring(0, l.IndexOf('"'));
                if (z1.Contains("</ul></li><liclass="))
                {
                    z1 = z1.Replace("</ul></li><liclass=", "af");
                }
                CountriesCodes.Add(z1);
                CountriesCodes.GroupBy(n => n).Any(c => c.Count() > 1);

                string z2 = parts[i].Substring(parts[i].LastIndexOf('>') + 1);
                if (z2.Contains("&amp;"))
                {
                    z2 = z2.Replace("&amp;", " & ");
                }
                CountriesNames.Add(z2);
                CountriesNames.GroupBy(n => n).Any(c => c.Count() > 1);
            }

            for (int i = 0; i < CountriesCodes.Count; i++)
            {
                CountriesFile.WriteLine("Country Code = " + CountriesCodes[i]);
                CountriesFile.WriteLine("Country Name = " + CountriesNames[i]);
            }

            CountriesFile.Close();
        }
    }
}

在 Form1 构造函数中:

public Form1()
        {
            InitializeComponent();

            GenerateCountries Countries = new GenerateCountries();
            Countries.Init();
            Countries.ExtractCountires();
        }

问题出在GenerateCountries类就行了:

Client.DownloadFile(CountriesHtmlAddress, CountriesHtmlFile);

有时它会在服务器端抛出异常。在许多情况下,它会抛出异常。

有时会抛出的第一个异常:

System.Net.WebException: '底层连接已关闭:一个 发送时发生意外错误。 IOException:无法读取数据 从传输连接:一个现有的连接被强行 被远程主机关闭。 SocketException:一个现有的连接是 被远程主机强行关闭

有时这也是第二个:

The remote server returned an error: (500) Internal Server Error.

我想做的是尝试每隔 15 或 20 秒继续下载一次,直到下载成功。 尝试下载,如果不成功等待20秒再尝试下载等等。

【问题讨论】:

标签: c# winforms


【解决方案1】:

WebClinet的异步方法有事件接受一个名为userToken的参数,你可以将它设置为正在下载的文件的信息(它的下载链接,它在要下载的文件数组中的索引等),那么当DownloadFileCompleted事件触发时,你可以检查它是否成功,它是否失败了你可以使用这个userToken重新下载文件:

using (WebClient wc = new WebClient())
{
    wc.DownloadFileCompleted += (s, e) =>
    {
        if(e.Error!=null)
        ((WebClient)s).DownloadFileAsync(new Uri((string)e.UserState), "C:\\" + ((string)e.UserState).Split('/').Last(), e.UserState)
        //instead of this line you may set a timer that would do the download after sometime
    };

    wc.DownloadFileAsync(new Uri("http://example.com/somefile.txt"), "C:\\somefile.txt", "http://example.com/somefile.txt");
}

【讨论】:

    【解决方案2】:
    public Task DownloadContentAsync(CancellationToken cancellationToken)
    {
      // download content here
    }
    
    public async Task RunAsync()
    {
      var succeeded = false;
      while(!succeeded)
      {
        var cts = new CancellationTokenSource(TimeSpan.FromSeconds(20));
        await DownloadContentAsync(cts.Token)
         .ContinueWith((x) => succeeded = x.IsCompleted);
      }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-03-11
      • 2015-01-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-25
      • 2020-12-22
      相关资源
      最近更新 更多