2015-03-25 57 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>