首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Webclient DownloadString冻结主表单

Webclient DownloadString冻结主表单
EN

Stack Overflow用户
提问于 2015-03-25 00:09:41
回答 2查看 1K关注 0票数 0

希望有人能帮我解决问题。

我试图使用以下代码获取网站的html代码:

代码语言:javascript
复制
        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;
        }

我需要这个函数中的字符串(Caller):

代码语言:javascript
复制
        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));,但它似乎不起作用,下载字符串时它仍然会冻结UI。

提前谢谢你!

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-03-25 12:21:20

为了防止阻塞UI,您的代码需要一直是异步的。

特别是这段代码将阻塞UI线程,直到下载完成:

代码语言:javascript
复制
Task<string> task = Task.Factory.StartNew<string>(() => DownloadString(add));
string html = task.Result;

您需要的是使用await来代替:

代码语言:javascript
复制
Task<string> task = Task.Run(() => DownloadString(add));
string html = await task;

这意味着您的get_html方法必须是async

代码语言:javascript
复制
public async Task<HtmlNode> get_htmlAsync(string add)

它的所有调用者都必须使用await,并成为async等等。您必须允许异步在调用树中一直增长。

票数 1
EN

Stack Overflow用户

发布于 2015-03-25 12:33:23

这里的问题是对task.Result的调用总是阻塞的(如果任务尚未准备好,调用线程将等待完成),所以UI线程将被阻塞,等待任务结果。如果您正在使用.Net Framework4 (@Stephen为4.5编写了一个解决方案),您需要做的是以如下方式使用延续。

代码语言:javascript
复制
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>,以便在其上使用延续。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29245259

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档