等待没有异步/等待的异步HTTP请求的响应

我正在开发一个Windows Forms应用程序的插件,它可以在地图上显示终端的位置(在WebBrowser控件中)。 案例如下:

  1. 用户点击按钮(调用插件);
  2. 创建异步HTTP请求(确定终端的坐标);
  3. 随着所有回复的收到 – 地图应该显示给用户。

我写了代码:

foreach (var terminal in terminals) { var webRequest = (HttpWebRequest)WebRequest.Create(GeoCoder.GeoCodeUrl + terminal.Address); var taskResp = Task.Factory.FromAsync(webRequest.BeginGetResponse, webRequest.EndGetResponse, terminal.Id); var taskResult = taskResp.ContinueWith(task => { // Parse the response }); runningTasks.Add(taskResult); } Task.WaitAll(runningTasks.ToArray()); // UI Thread blocks here! webBrowser1.DocumentText = ... 

它会阻止UI线程,因为我必须等到我才能显示地图之前得到所有响应(坐标)。 我想知道如何避免这种情况(没有同步的http请求)?

PS我知道如何使用async / await但不能使用它们 – 我必须使用.NET 4.0和VS2010 – Microsoft.Bcl.Async无法帮助)。

据我所知,你很惊讶如何在c#4.0中做到这一点。

这并不难,记住以前在.Net 1.0中做过这类工作的人,甚至在那之前:)

 var uiTaskScheduler = TaskScheduler.FromCurrentSynchronizationContext(); Task.Factory.ContinueWhenAll(runningTasks.ToArray(), antecedents => { webBrowser1.DocumentText = ...//This runs in UI thread },CancellationToken.None, TaskContinuationOptions.None,uiTaskScheduler ); 

我错过了什么吗?

您可以使用System.Threading.ThreadPool.QueueUserWorkItem来启动您的代码,该代码将在与UI的单独线程上运行它,但请记住,您需要调用webBrowser1.DocumentText = ...因为如果您将获得exception惯于。 希望这可以帮助。

BackgroundWorker类提供了一种简单易用的方法来远离UI线程执行工作。 在.DoWork事件处理程序中执行您的工作,完成后,将调用UI线程来执行.RunWorkerComplete事件处理程序,您可以在其中使用映射更新UI。

 class Form1 { private System.ComponentModel.BackgroundWorker bgw; public Form1() { bgw = new BackgroundWorker(); bgw.DoWork += WorkMethod; bgw.RunWorkerCompleted += WorkCompleteMethod; } private void Button1_Click(object sender, eventargs e) { if (!bgw.IsBusy) { bgw.RunWorkerAsync(); } } private void WorkMethod(object sender, DoWorkEventArgs e) { //perform work //set result to e.Result } private void WorkCompleteMethod(object sender, RunWorkerCompletedEventArgs e) { //extract result from eventargs //update ui } }