Правильный способ ожидания всех задач при обновлении потока пользовательского интерфейса - PullRequest
0 голосов
/ 09 января 2019

Я пытаюсь загрузить исходный код страницы с нескольких URL-адресов, используя задачи для загрузки нескольких сайтов одновременно. Проблема в том, что я хочу, чтобы пользовательский интерфейс обновлялся по мере выполнения каждой отдельной задачи. Когда я пытаюсь подождать все задачи, он перестает обновлять пользовательский интерфейс, пока все они не завершатся. Вот текущий код, который я использую.

РЕДАКТИРОВАТЬ: я предполагаю, что я был проголосовал за, потому что я не объяснил достаточно хорошо Я думаю, что лучший способ выразить это - почему continue не запускается перед Task.WaitAll. Я хочу, чтобы интерфейс обновлялся при каждом завершении загрузки источника. Как только все это будет завершено, список будет обновлен, чтобы пользователь знал, что все сделано.

   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 голосов
/ 10 января 2019

Вы действительно должны использовать асинхронный метод загрузки, основанный на 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...");
}
...