Форум программистов, компьютерный форум, киберфорум
C# .NET
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.86/7: Рейтинг темы: голосов - 7, средняя оценка - 4.86
315 / 244 / 149
Регистрация: 03.10.2017
Сообщений: 886
Записей в блоге: 1

Вызов WebBrowser в отдельном потоке

05.10.2020, 11:30. Показов 1494. Ответов 13
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Скажу честно, в потоках я слабоват. Есть таска.
Нужно список URL-ов прогрузить в браузере и выполнить в нём скрипт. Так как используется веб браузер он не все скрипты подгружает, возможно, можно использовать что-то другое, но это не самая главная проблема.

Чтобы отловить загрузку страницы необходимо её запустить в отдельном потоке и отловить событие. Можно ли как-то в консольном приложение запустить в отдельном потоке браузер и просто ему накидывать url ы.
В данный момент я сделал реализацию, но она странная и мне кажется, что я делаю что-то ни так, так как со временем очень сильно разжирается по памяти

Вызов
Кликните здесь для просмотра всего текста

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
for (var j = 1; j < urlsList.Count; j++)
                    {
                        Console.WriteLine(
                            $"Файл: {i + 1}/{fileList.Count}. Прогресс: {j}/{urlsList.Count - 1}({Math.Truncate((double) j * 100 / (urlsList.Count - 1))}%)");
                        var fileString = urlsList[j];
                        var splitList = Parser.SplitList(fileString, ',');
                        var manualResetEvent = new ManualResetEvent(false);
                        Thread th = null;
                        try
                        {
                            th = new Thread(() =>
                            {
                                codeAnalyzer.RunBrowserThread(
                                    new BrowserObject(splitList[indexWebsite], manualResetEvent, fileString));
                            });
                            th.Start();
                            listEvent.Add(manualResetEvent);
                        }
                        catch (Exception ex)
                        {
                            manualResetEvent.Set();
                            errorList.Add(fileString);
                            Console.WriteLine(indexWebsite < splitList.Count
                                ? $"Error parse: {ex.Message}. Url: {splitList[indexWebsite]}"
                                : $"Error parse: {ex.Message}");
                        }
 
                        if (!th.Join(new TimeSpan(0, 0, 10)))
                        {
                            th.Abort();
                            manualResetEvent.Set();
                        }
 
                        WaitHandle.WaitAll(new WaitHandle[] {manualResetEvent});
                    }


Обработка
Кликните здесь для просмотра всего текста

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
 public void RunBrowserThread(object state)
        {
            var obj = (BrowserObject) state;
            Uri url = new Uri((string) obj.url);
            var th = new Thread(() =>
            {
                var webBrowser = new WebBrowser();
                webBrowser.ScriptErrorsSuppressed = true;
 
                webBrowser.DocumentCompleted += (object sender, WebBrowserDocumentCompletedEventArgs e) =>
                {
                    var br = sender as WebBrowser;
                    if (br.Url == e.Url)
                    {
                        AddScriptInDocument(br, obj);
                        br.Dispose();
                        Application.ExitThread();
                        obj.ManualResetEvent.Set();
                    }
                };
 
                webBrowser.ProgressChanged += (object sender, WebBrowserProgressChangedEventArgs e) =>
                {
                    if (e.CurrentProgress == e.MaximumProgress)
                    {
                        obj.ManualResetEvent.Set();
                    }
                };
                webBrowser.Navigate(url);
                Application.Run();
            });
            th.SetApartmentState(ApartmentState.STA);
            th.Start();
            
        }
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
05.10.2020, 11:30
Ответы с готовыми решениями:

Рекурсия. Вызов в отдельном потоке
Напишите программу, в которой метод будет вызываться рекурсивною. Каждый новый вызов метода выполняется в отдельном потоке. Не...

Вызов функции с задержками в отдельном потоке
Добрый вечер, господа. В общем, возникла у меня небольшая совсем проблемка при работе с контроллом trackBar. Собственно, что мне от этого...

Создать приложение, в отдельном потоке вычисляющее значение w и непрерывно обновляющее его в потоке
Ребят, с потоками не работал не когда. Есть задание , я понимаю что хотят, а вот как сделать потоками хз . Создайте приложение, в...

13
17 / 14 / 7
Регистрация: 04.02.2017
Сообщений: 486
05.10.2020, 23:01
да конечно можно используйте лучше всего async await.

C#
1
2
3
4
public async void ExecuteUrl()
{
     await Task.Run(()=>{//Ваша задача});
}
0
315 / 244 / 149
Регистрация: 03.10.2017
Сообщений: 886
Записей в блоге: 1
06.10.2020, 08:15  [ТС]
FerrariF70, асирхронщинный метод перестанет кушать память?
0
17 / 14 / 7
Регистрация: 04.02.2017
Сообщений: 486
06.10.2020, 17:53
Цитата Сообщение от Masson1848 Посмотреть сообщение
асирхронщинный метод перестанет кушать память?
У вас где именно память кушает на самом браузере или само консольное приложение? В принцепе сам браузер грузит очень сильно память а темболее если ещё много вкладок.
0
315 / 244 / 149
Регистрация: 03.10.2017
Сообщений: 886
Записей в блоге: 1
06.10.2020, 22:34  [ТС]
FerrariF70, Браузер то кушает, но я же его закрываю каждый раз поток и соответственно браузер, значит он не может выжирать память, а со временем, а это примерно спустя 600 сайтов становится 1,5гб на приложение
0
17 / 14 / 7
Регистрация: 04.02.2017
Сообщений: 486
07.10.2020, 00:41
Masson1848, Мне не совсем понятно цель вашей программы, вы пытаетесь запустить допустим 200 ссылок в один момент при этом выделяя для каждой ссылки свой поток, я правильно понимаю? если это так то у вас конечно будет очень много сжиратся памяти, и это не совсем хорошо для компьютера когда столь абильная многопоточность. Или же вы запускаете в одном потоке много URL ов.

1. Когда вы запускаете поток какое событие вы выжидаете?
2. Через какой период времени поток должен закрыться?
3. Как вы знаете какой именно поток вы закрываете? потому что если вы говорите что вы закрываете браузер а память всёровно не освобождаеться так может вы на самом деле не закрываете поток.
0
315 / 244 / 149
Регистрация: 03.10.2017
Сообщений: 886
Записей в блоге: 1
07.10.2020, 13:04  [ТС]
FerrariF70,
1) Я запускаю поток и выжидаю событие ManulResetEvent. Я его прокидываю в поток. Внутри жду DocumentComplete выполняю скрипт, забираю результат и закрываю поток, через Application.ExitThread. Если у меня через 10 секунд не открывается страница я поток закрываю через .Abort();

2) Либо сам закрыться, по исполнению. Либо по срабатывания события ManualResetEvent, либо через 10 секунд.

3) Я открываю новый поток, и ожидаю его завершение через WaitHandle
0
17 / 14 / 7
Регистрация: 04.02.2017
Сообщений: 486
07.10.2020, 22:13
C#
1
2
3
4
5
6
7
8
9
try
 {
 th = new Thread(() =>
 {
 codeAnalyzer.RunBrowserThread(
 new BrowserObject(splitList[indexWebsite], manualResetEvent, fileString));
 });
 th.Start();
 listEvent.Add(manualResetEvent);
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
 var th = new Thread(() =>
            {
                var webBrowser = new WebBrowser();
                webBrowser.ScriptErrorsSuppressed = true;
 
                webBrowser.DocumentCompleted += (object sender, WebBrowserDocumentCompletedEventArgs e) =>
                {
                    var br = sender as WebBrowser;
                    if (br.Url == e.Url)
                    {
                        AddScriptInDocument(br, obj);
                        br.Dispose();
                        Application.ExitThread();
                        obj.ManualResetEvent.Set();
                    }
                };

Скажите а для чего вам нужен один поток в нутри другова? и не видно где вы закрываете внутрений поток (где происходит обработка). смотрите что сделайте запустите программу в отладке затем откройте окно Паралельные стеки это находится в вкладке:
Отладка => окна => параллельные стеки. Посмотрите там что действительно все потоки закрываются и нет утечек. Только запустите для примера 10 потков а то 600 замучаетесь отслеживать.
1
315 / 244 / 149
Регистрация: 03.10.2017
Сообщений: 886
Записей в блоге: 1
07.10.2020, 22:31  [ТС]
FerrariF70, да я уже отказался от встроенного браузера, так как он больше половины сайтов не прогружает из-за ошибки скриптов и перешёл на dotnetbrowser, спасибо за помощь, про параллельные стеки не знал, будет свободное время, посмотрю что у меня в этой программе не Так
0
1152 / 860 / 263
Регистрация: 30.04.2009
Сообщений: 3,603
08.10.2020, 01:20
Браузер то кушает, но я же его закрываю каждый раз поток и соответственно браузер
Masson1848, вкорне неверно. закрытие потока не освобождает память. WebBrowser использует неуправляемые ресурсы. В лучшем случае они будут освобождены при вызове деструктора, если он есть, а если нету то не будут освобождены вообще (до закрытия процесса)
0
315 / 244 / 149
Регистрация: 03.10.2017
Сообщений: 886
Записей в блоге: 1
08.10.2020, 07:08  [ТС]
nicolas2008, это перед завершением потока я должен вызвать dispose? Или можно использоватьusing для WebBrowser
0
1152 / 860 / 263
Регистрация: 30.04.2009
Сообщений: 3,603
08.10.2020, 10:59
Masson1848, лучше using
1
315 / 244 / 149
Регистрация: 03.10.2017
Сообщений: 886
Записей в блоге: 1
08.10.2020, 22:06  [ТС]
nicolas2008, я попробую дойти до этого решения и исправить его, но как я писал выше. Я перешёл на DotNetBrowser и решил свою задачу. Работает даже лучше, так как WebBrowser в основе использует ИЕ и он игнорирует 50% сайтов
0
1152 / 860 / 263
Регистрация: 30.04.2009
Сообщений: 3,603
08.10.2020, 23:51
Masson1848, ни в коем случае не хочу убедить вас вернуться к использованию WebBrowser. он безнадежно устарел, а обновления не предвидится.
Просто совет на будущее - вызывайте Dispose или используйте using для всех обьектов которые поддерживают IDisposable иначе с большей вероятностью будут проблемы с освобождением памяти.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
08.10.2020, 23:51
Помогаю со студенческими работами здесь

Пикчербокс в отдельном потоке
Добрый день! Подскажите, кто знает, как добавить picturebox в отдельный поток (там будет анимация) желательно код. Заранее спасибо!

Форма в отдельном потоке
Я создал форму, которая будет отображаться во время загрузки приложения (в ней меняется прозрачность (она тоже что-то делает:))): она...

FileWatch в отдельном потоке
Добрый день, возникла проблема в реализации. Нужно что бы изменения файлов мониторились в отдельном потоке, и при изменении выводились в...

ICollectionView в отдельном потоке
Добрый вечер!) Ребят объясните мне как правильно работать с потоками в WPF. Вот смотрите есть у меня Datagrid который прибинден к...

Окно в отдельном потоке
Привет, вопрос заключается в том как поступить. У меня есть редактор карт для своего приложения. Он должен создавать Grid определенных...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
14
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL3_image
8Observer8 10.02.2026
Содержание блога Библиотека SDL3_image содержит инструменты для расширенной работы с изображениями. Пошагово создадим проект для загрузки изображения формата PNG с альфа-каналом (с прозрачным. . .
Установка Qt-версии Lazarus IDE в Debian Trixie Xfce
volvo 10.02.2026
В общем, достали меня глюки IDE Лазаруса, собранной с использованием набора виджетов Gtk2 (конкретно: если набирать текст в редакторе и вызвать подсказку через Ctrl+Space, то после закрытия окошка. . .
SDL3 для Web (WebAssembly): Работа со звуком через SDL3_mixer
8Observer8 08.02.2026
Содержание блога Пошагово создадим проект для загрузки звукового файла и воспроизведения звука с помощью библиотеки SDL3_mixer. Звук будет воспроизводиться по клику мышки по холсту на Desktop и по. . .
SDL3 для Web (WebAssembly): Основы отладки веб-приложений на SDL3 по USB и Wi-Fi, запущенных в браузере мобильных устройств
8Observer8 07.02.2026
Содержание блога Браузер Chrome имеет средства для отладки мобильных веб-приложений по USB. В этой пошаговой инструкции ограничимся работой с консолью. Вывод в консоль - это часть процесса. . .
SDL3 для Web (WebAssembly): Обработчик клика мыши в браузере ПК и касания экрана в браузере на мобильном устройстве
8Observer8 02.02.2026
Содержание блога Для начала пошагово создадим рабочий пример для подготовки к экспериментам в браузере ПК и в браузере мобильного устройства. Потом напишем обработчик клика мыши и обработчик. . .
Философия технологии
iceja 01.02.2026
На мой взгляд у человека в технических проектах остается роль генерального директора. Все остальное нейронки делают уже лучше человека. Они не могут нести предпринимательские риски, не могут. . .
SDL3 для Web (WebAssembly): Вывод текста со шрифтом TTF с помощью SDL3_ttf
8Observer8 01.02.2026
Содержание блога В этой пошаговой инструкции создадим с нуля веб-приложение, которое выводит текст в окне браузера. Запустим на Android на локальном сервере. Загрузим Release на бесплатный. . .
SDL3 для Web (WebAssembly): Сборка C/C++ проекта из консоли
8Observer8 30.01.2026
Содержание блога Если вы откроете примеры для начинающих на официальном репозитории SDL3 в папке: examples, то вы увидите, что все примеры используют следующие четыре обязательные функции, а. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru