我正在开发一个Windows Forms应用程序的插件,它可以在地图上显示终端的位置(在WebBrowser控件中)。案例如下:
我写了代码:
foreach (var terminal in terminals)
{
var webRequest = (HttpWebRequest)WebRequest.Create(GeoCoder.GeoCodeUrl + terminal.Address);
var taskResp = Task.Factory.FromAsync<WebResponse>(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请求)?
P.S。我知道如何使用async / await但不能使用它们 - 我必须使用.NET 4.0和VS2010 - Microsoft.Bcl.Async无法帮助。)
答案 0 :(得分:1)
据我所知,你很惊讶它是如何在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 );
我错过了什么吗?
答案 1 :(得分:0)
您可以使用System.Threading.ThreadPool.QueueUserWorkItem
启动您的代码,该代码将在与UI的单独线程上运行,但请记住,您需要调用webBrowser1.DocumentText = ...
,因为如果您赢了将获得异常“T。
希望这会有所帮助。
答案 2 :(得分:0)
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
}
}