在更新 UI 线程的同时等待所有任务的正确方法
Proper way to wait all tasks while still updating the UI thread
我正在尝试使用任务从多个 url 下载页面源代码以一次下载多个站点。问题是我想在每个任务完成时保持 UI 更新。当我尝试等待所有任务时,它会停止更新 UI 直到它们全部完成。这是我当前使用的代码。
编辑:我假设我因为解释得不够好而被否决了。我想更好的表达方式是为什么 continueWith 在 Task.WaitAll 之前不是 运行。我希望 UI 在每次完成下载源时更新。全部完成后,列表框将更新,让用户知道一切都已完成。
private void btnGetPages_Click(object sender, EventArgs e)
{
for (int i = 1; i < 11; i++)
{
string url = $"http://someURL/page-{i}.html";
listBoxStatus.Items.Add($"Downloading source from {url}...");
Task t = new Task(() =>
{
DownloadSource(url);
});
t.ContinueWith(prevTask => listBoxStatus.Items.Add($"Finished Downloading {url} source..."), TaskScheduler.FromCurrentSynchronizationContext());
tasks.Add(t);
t.Start();
}
Task.WaitAll(tasks.ToArray());
listBoxStatus.Items.Add("All Source files have completed...");
}
private void DownloadSource(string url)
{
var web = new HtmlWeb();
var doc = web.Load(url);
pageSource += doc.Text;
}
您确实应该使用基于 HttpClient
的异步下载方法,而不是您显示的同步方法。没有那个,我会用这个:
private async Task DownloadSourceAsync(string url)
{
await Task.Run(() => DownloadSource(url));
listBoxStatus.Items.Add($"Finished Downloading {url} source...");
}
然后,您可以使您的 btnGetPages_Click
方法像这样:
private async void btnGetPages_Click(object sender, EventArgs e)
{
var tasks = new List<Task>();
for (int i = 1; i < 11; i++)
{
string url = $"http://someURL/page-{i}.html";
listBoxStatus.Items.Add($"Downloading source from {url}...");
tasks.Add(DownloadSourceAsync(url));
}
Task.WaitAll(tasks.ToArray());
listBoxStatus.Items.Add("All Source files have completed...");
}
我正在尝试使用任务从多个 url 下载页面源代码以一次下载多个站点。问题是我想在每个任务完成时保持 UI 更新。当我尝试等待所有任务时,它会停止更新 UI 直到它们全部完成。这是我当前使用的代码。
编辑:我假设我因为解释得不够好而被否决了。我想更好的表达方式是为什么 continueWith 在 Task.WaitAll 之前不是 运行。我希望 UI 在每次完成下载源时更新。全部完成后,列表框将更新,让用户知道一切都已完成。
private void btnGetPages_Click(object sender, EventArgs e)
{
for (int i = 1; i < 11; i++)
{
string url = $"http://someURL/page-{i}.html";
listBoxStatus.Items.Add($"Downloading source from {url}...");
Task t = new Task(() =>
{
DownloadSource(url);
});
t.ContinueWith(prevTask => listBoxStatus.Items.Add($"Finished Downloading {url} source..."), TaskScheduler.FromCurrentSynchronizationContext());
tasks.Add(t);
t.Start();
}
Task.WaitAll(tasks.ToArray());
listBoxStatus.Items.Add("All Source files have completed...");
}
private void DownloadSource(string url)
{
var web = new HtmlWeb();
var doc = web.Load(url);
pageSource += doc.Text;
}
您确实应该使用基于 HttpClient
的异步下载方法,而不是您显示的同步方法。没有那个,我会用这个:
private async Task DownloadSourceAsync(string url)
{
await Task.Run(() => DownloadSource(url));
listBoxStatus.Items.Add($"Finished Downloading {url} source...");
}
然后,您可以使您的 btnGetPages_Click
方法像这样:
private async void btnGetPages_Click(object sender, EventArgs e)
{
var tasks = new List<Task>();
for (int i = 1; i < 11; i++)
{
string url = $"http://someURL/page-{i}.html";
listBoxStatus.Items.Add($"Downloading source from {url}...");
tasks.Add(DownloadSourceAsync(url));
}
Task.WaitAll(tasks.ToArray());
listBoxStatus.Items.Add("All Source files have completed...");
}