2015-03-25 99 views
0

希望有人可以幫我解決我的問題。Webclient DownloadString凍結主窗體

我嘗試使用下面的代碼來獲得一個網站的HTML代碼:

 public string DownloadString(string add) 
     { 
      string html = "";    
      using (WebClient client = new WebClient()) 
      { 
       client.Proxy = null; 
       client.Headers.Add("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.0.3705;)"); 
       while (html == "") 
       { 
        try 
        { 
         html = client.DownloadString(add); 

        } 
        catch (WebException e) 
        { 
         html = ""; 
        } 
       } 
       client.Dispose(); 
      } 
      return html; 
     } 

我需要在字符串中的這個功能(來電):

 public HtmlNode get_html(string add) 
     { 
      add_val(add); 
      Uri madd = new Uri(add); 
      Stopwatch timer = Stopwatch.StartNew(); 
      Task<string> task = Task.Factory.StartNew<string> 
     (() => DownloadString(add)); 
      string html = task.Result; 
      //string html = DownloadString(add); 
      HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument(); 
      //doc.Load(new StringReader(html)); 
      doc.LoadHtml(html); 
      HtmlNode root = doc.DocumentNode; 
      timer.Stop(); 
      TimeSpan timespan = timer.Elapsed; 
      label18.Text = String.Format("{0:00}:{1:00}:{2:00}", timespan.Minutes, timespan.Seconds, timespan.Milliseconds/10);    
      return root; 
     } 

我曾嘗試html = await client.DownloadStringTaskAsync(new Uri(add));但它似乎沒有工作,它仍然凍結用戶界面,當我下載一個字符串。

預先感謝您!

+0

可能重複的[如何使用WebClient而不阻止UI?](http://stackoverflow.com/questions/6118796/how-to-use-webclient-without-blocking-ui) – 2015-03-25 00:17:16

+0

我試過了,它仍然凍結用戶界面。 – NoobCS 2015-03-25 00:19:44

+0

你仍然在你的用戶界面的同一線程上運行...請使用** BackgroundWorker ** ..非常類似於**定時器** - 將授予您運行代碼而不凍結的東西 – ymz 2015-03-25 00:39:41

回答

1

爲了防止阻塞UI,您的代碼需要異步一路

Task<string> task = Task.Factory.StartNew<string>(() => DownloadString(add)); 
string html = task.Result; 

你需要的是使用await代替:

Task<string> task = Task.Run(() => DownloadString(add)); 
string html = await task; 

這意味着你get_html方法必須是async

,直至下載完成此代碼,特別是阻塞UI線程:

public async Task<HtmlNode> get_htmlAsync(string add) 

其所有來電者必須使用await,併成爲async等。您必須允許異步通過調用者樹一路增長。

1

這裏的問題是,調用task.Result總是阻塞(如果任務沒有準備好,調用線程將等待完成),所以你的UI線程將被阻塞,等待任務結果。如果你使用.Net Framework 4(@Stephen爲4.5寫了一個解決方案),你需要做的是以下面的方式使用continuation。

public void get_html(string add) 
     { 
      add_val(add); 
      Uri madd = new Uri(add); 
      Stopwatch timer = Stopwatch.StartNew(); 
      Task.Factory.StartNew<string>(() => DownloadString(add)) 
       .ContinueWith(t => { 
        string html = task.Result; 
        HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument(); 
        doc.LoadHtml(html); 
        HtmlNode root = doc.DocumentNode; 
        timer.Stop(); 
        TimeSpan timespan = timer.Elapsed; 
        label18.Text = String.Format("{0:00}:{1:00}:{2:00}", timespan.Minutes, timespan.Seconds, timespan.Milliseconds/10);    
        // 
        Update UI with results here 
        // 
       }, TaskScheduler.FromCurrentSynchronizationContext()); 
     } 

或者,你可以以使用延續其上設置get_html返回類型Task<string>Task<HtmlNode>