0

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

//Часть кода из главной функции
load = false;
WebBrowser wb = new WebBrowser();   
wb.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(DocumentLoad);
wb.Navigate(@"https://instagram.com/");
while (!load) { Thread.Sleep(40); };

И код обработчика события загрузки страницы:

public void DocumentLoad(object sender, WebBrowserDocumentCompletedEventArgs e)
{
    load = true;
}
artebel
  • 13
  • 1
    вы это while (!load) { Thread.Sleep(40); }; в UI потоке запустили? Если да, то DocumentLoad просто никода не отработает, так как поток, который должен это отработать, занят вашим циклом – tym32167 May 20 '19 at 09:27
  • @tym32167 Понял, то есть, мне для этого надо создать дополнительный поток, так ведь? Какой-нибудь асинхронный например – artebel May 20 '19 at 09:33
  • А что означает «без Control» в заголовке? – default locale May 20 '19 at 09:37

1 Answers1

1

Вы блокируете поток в котором выполняется Ваш код, в том числе и обработчик DocumentLoad соответственно, load=true не выполняется.

Для обработки завершения загрузки нужно подписаться на событие WebBrowser.DocumentCompleted и код, который зависит от загрузки страницы перенести непосредственно в обработчик события.

Полагаю, что в полном коде есть какие-то действия после цикла и он выглядит примерно так:

load = false;
WebBrowser wb = new WebBrowser();   
wb.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(DocumentLoad);
wb.Navigate(@"https://instagram.com/");
while (!load) { Thread.Sleep(40); };
//какой-то код, который работает с загруженной страницей

...
public void DocumentLoad(object sender, WebBrowserDocumentCompletedEventArgs e)
{
    load = true;
}

Нужно переделать его во что-то вроде:

WebBrowser wb = new WebBrowser();   
wb.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(DocumentLoad);
wb.Navigate(@"https://instagram.com/");
//здесь больше ничего не делаем

...
public void DocumentLoad(object sender, WebBrowserDocumentCompletedEventArgs e)
{
    //какой-то код, который работает с загруженной страницей
}

  • Я попробовал что-то похожее. Теперь в главной функции создается поток для метода, в котором как раз объявляю WebBrowser, выполняю Navigate и подписывают на событие завершения загрузки страницы. Но проблема все равно остается неизменной, даже в потоке не срабатывает DocumentLoad – artebel May 20 '19 at 09:56
  • @artebel Что-то это совсем не похоже на то, что я написал :-) Если у Вас в одном и том же потоке бесконечный цикл и обработка события, то обработка события не произойдет. Мой ответ: отказываться от цикла и флагов и использовать обработчик по назначению. – default locale May 20 '19 at 09:58
  • @artebel вы пробовали конкретно тот код, что в ответе? Нет смысла код усложнять дополнительными потоками, особенно учитывая, что UI контролы работат только в UI потоке – tym32167 May 20 '19 at 09:59
  • Формально, обработчик события-то лежит на втором потоке, там же, где и Navigate. – artebel May 20 '19 at 10:02
  • @artebel Не знаю, я второго потока не видел :) Я предлагаю подход без второго потока. Вы его попробовали? – default locale May 20 '19 at 10:04
  • У меня попросту не получится сделать через обработчик по назначению, потому что на вход подается список ссылок, которые я в цикле должен был подгружать и работать в отдельности с каждой из них. То есть, мне по-любому нужно толкать в функцию бесконечный цикл хотя бы для отслеживания завершения предыдущего обработчика загруженной страницы, а это опять будет убивать работу программы – artebel May 20 '19 at 10:09
  • @artebel WebBrowser корректно может работать в фоновом потоке только если в нем инициализирован Single-Threaded COM Apatment и запущен цикл обработки сообщений. В добавок, любое взаимодействие с ним должно осуществляться только из этого потока. Если у вас все это не реализовано, ничего не может заработать, даже теоретически. – MSDN.WhiteKnight May 20 '19 at 10:16
  • @artebel Вот это все пожалуй нужно расписать в тексте вопроса. Еще вопрос: нужно ли Вам обрабатывать ссылки последовательно или параллельно? Если параллельно то будет ли для каждого потока свой WebBrowser (нюансы с последовательностью событий и с настройкой потоков) или он должен быть один (нюансы с многопоточным доступом)? – default locale May 20 '19 at 10:16
  • @artebel "толкать в функцию бесконечный цикл хотя бы для отслеживания завершения предыдущего обработчика" - этого не нужно делать никогда. Используйте нормальные средства синхронизации потоков, вроде ManualResetEvent, либо асинхронные методы + await – MSDN.WhiteKnight May 20 '19 at 10:18