2016-08-28 49 views
0

我有一個程序,它獲取的HTML代碼〜500的網頁,每5分鐘獲取HTML響應分別失敗後第一失效

它運行正確,直到第一失效(無法下載源在6秒)

後所有的線程將失敗

,如果我重新啓動程序,它再次運行正常,直到......

在那裏我錯了,我應該做的做的更好?

此功能運行,每5分鐘:

 foreach (Company company in companies) 
     { 
      string link = company.GetLink(); 

      Thread t = new Thread(() => F(company, link)); 
      t.Start(); 
      if (!t.Join(TimeSpan.FromSeconds(6))) 
      { 
       Debug.WriteLine(company.Name + " Fails"); 
       t.Abort(); 
      } 
     } 

這個功能下載HTML代碼

private void F(Company company, string link) 
    { 
     try 
     { 
      string htmlCode = GetInformationFromWeb.GetHtmlRequest(link); 
      company.HtmlCode = htmlCode; 
     } 
     catch (Exception ex) 
     { 
     } 
    } 

這個類:

public class GetInformationFromWeb 
{ 
    public static string GetHtmlRequest(string url) 
    { 
     using (MyWebClient client = new MyWebClient()) 
     { 
      client.Encoding = Encoding.UTF8; 
      string htmlCode = client.DownloadString(url); 
      return htmlCode; 
     } 
    } 
} 

和Web客戶端類

public class MyWebClient : WebClient 
{ 
    protected override WebRequest GetWebRequest(Uri address) 
    { 
     HttpWebRequest request = base.GetWebRequest(address) as HttpWebRequest; 
     request.AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip; 
     return request; 
    } 
} 
+0

返回的異常是什麼? – Legends

+0

@Legends在輸出 – mojtaba357

+0

中有很多「線程異常終止」,你可以在你的catch塊中使用'Continue',參考這個鏈接:http://stackoverflow.com/questions/654113/how-do-i-skip-an -iteration對的一-的foreach環 –

回答

1

如果您的foreach正在循環500多家公司,並且每個公司都在創建一個新線程,則可能是因特網速度可能成爲瓶頸,您將在6秒內收到超時,並且經常失敗。

我建議你嘗試一下並行。注意MaxDegreeOfParallelism,它設置最大並行執行量。你可以調整它來滿足你的需求。

Parallel.ForEach(companies, new ParallelOptions { MaxDegreeOfParallelism = 10 }, (company) => 
      { 
       try 
       { 
        string htmlCode = GetInformationFromWeb.GetHtmlRequest(company.link); 
        company.HtmlCode = htmlCode; 
       } 
       catch(Exception ex) 
       { 
        //ignore or process exception 
       } 
      }); 
1

我有四個基本的建議:中

  1. 使用HttpClient,而不是過時的WebClientHttpClient可以本機處理異步操作,並具有更多的靈活性來利用。您甚至可以將下載內容讀取到不同線程上的字符串/流,因爲您可以配置await不安排您的操作。或者甚至編程HttpClientHandler在6秒鐘後中斷,如果超過這個時間,則編程爲TaskCanceledException
  2. 避免吞嚥異常(就像您在F函數中那樣),因爲它會打破調試和混淆問題的真正原因。在正常操作過程中,正確編寫的程序絕不會引發異常。
  3. 您正在以無用的方式使用線程,它們甚至沒有重疊;他們只是在等待彼此開始,因爲在每個線程啓動後你都鎖定了調用循環。在.NET中它會更好做使用Task S(例如多任務,稱他們爲Task.Run(async delegate() { await yourTask(); })(或AsyncContext.Run(...)如果你需要UI訪問),它不會阻止任何東西。
  4. 整個GetInformationFromWeb類是毫無意義時刻 - 而且你也無意義地產生了多個客戶端對象,因爲一個HTTP客戶端對象可以處理多個請求(如果你使用HttpClient,即使沒有額外的臃腫 - 你只需要將它作爲靜態全局變量實例化一次,然後調用它從任何地方用client.GetStringAsync(Uri uri)這麼小的代碼

OT:這是某種學術項目嗎?