C# Webclient下载字符串冻结主窗体

C# Webclient下载字符串冻结主窗体,c#,multithreading,webclient,C#,Multithreading,Webclient,希望有人能帮我解决我的问题 我正在尝试使用以下代码获取网站的html代码: public string DownloadString(string add) { string html = ""; using (WebClient client = new WebClient()) { client.Proxy = null;

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

我正在尝试使用以下代码获取网站的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;
        }
我需要这个函数中的字符串(调用者):

publicHTMLNodeGet\uHTML(字符串添加)
{
添加值(添加);
urimadd=新的Uri(添加);
秒表计时器=Stopwatch.StartNew();
Task Task=Task.Factory.StartNew
(()=>下载字符串(添加));
字符串html=task.Result;
//字符串html=下载字符串(添加);
HtmlAgilityPack.HtmlDocument doc=新的HtmlAgilityPack.HtmlDocument();
//doc.Load(新的StringReader(html));
doc.LoadHtml(html);
HtmlNode root=doc.DocumentNode;
timer.Stop();
TimeSpan TimeSpan=计时器。已用时间;
label18.Text=String.Format(“{0:00}:{1:00}:{2:00}”,timespan.Minutes,timespan.Seconds,timespan.millizes/10);
返回根;
}
我尝试了
html=await client.downloadstringtasksync(新Uri(add))但它似乎不起作用,当我下载字符串时,它仍然会冻结UI


提前谢谢你

为了防止阻塞UI,您的代码需要始终是异步的

在下载完成之前,此代码会阻塞UI线程:

Task<string> task = Task.Factory.StartNew<string>(() => DownloadString(add));
string html = task.Result;
这意味着您的
get\u html
方法必须是
async

public async Task<HtmlNode> get_htmlAsync(string add)
public异步任务get\u htmlAsync(字符串添加)

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

这里的问题是对
任务的调用。结果
总是阻塞(如果任务未准备好,调用线程将等待完成),因此您的UI线程将被阻塞,等待任务结果。如果您使用的是.NETFramework4(@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());
        }
public void get_html(字符串添加)
{
添加值(添加);
urimadd=新的Uri(添加);
秒表计时器=Stopwatch.StartNew();
Task.Factory.StartNew(()=>DownloadString(add))
.ContinueWith(t=>{
字符串html=task.Result;
HtmlAgilityPack.HtmlDocument doc=新的HtmlAgilityPack.HtmlDocument();
doc.LoadHtml(html);
HtmlNode root=doc.DocumentNode;
timer.Stop();
TimeSpan TimeSpan=计时器。已用时间;
label18.Text=String.Format(“{0:00}:{1:00}:{2:00}”,timespan.Minutes,timespan.Seconds,timespan.millizes/10);
//
在此处使用结果更新UI
//
},TaskScheduler.FromCurrentSynchronizationContext());
}

或者,您可以将
get_html
return type设置为
Task
Task
,以便在其上使用continuation。

可能重复我尝试过的,但它仍然冻结UI。您仍然在UI的同一线程上运行。。。请使用BackgroundWorker。。非常类似于计时器-将允许您运行代码而不冻结内容如何从backgroundworker获得结果?调用
任务。结果总是阻塞。
public async Task<HtmlNode> get_htmlAsync(string add)
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());
        }