等待所有任务,同时仍更新UI线程的正确方法

时间:2019-01-08 21:35:45

标签: async-await task ui-thread

我正在尝试使用任务一次下载多个站点的方式从多个URL下载页面源。问题是我想在每个任务完成时保持UI更新。当我尝试等待所有任务时,它将停止更新UI,直到所有任务完成为止。这是我正在使用的当前代码。

编辑:我假设我因投票解释不充分而被否决。我想一个更好的方法是为什么在Task.WaitAll之前不运行continueWith。我希望用户界面在下载源的每次完成时都进行更新。完成所有操作后,将更新列表框,以使用户知道一切已完成。

   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;
    }

1 个答案:

答案 0 :(得分:1)

您确实应该使用基于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...");
}