#c_sharp #webbrowser
Поток с WebBrowser после определённой итерации зависает в ожидании примерно на 5 минут в коде потока: while (wb.ReadyState != WebBrowserReadyState.Complete) { System.Windows.Forms.Application.DoEvents(); } где значение состояния равно: wb.ReadyState == Uninitialized или Interactive в итоге возвращает страницу "Navigation canceled" - либо возвращает её уже с 5 минутными задержками. Почему компонент WebBrowser использует IE как 7-ой версии, если у меня в системе стоит IE8? Почему компонент WebBrowser перестаёт отдавать страницы? Почему объём память растёт приложения и в итоге занимает около 800 мб? У меня стоит задача сохранить отображение страницы на жёсткий диск, используя консольное приложение. Возможно можно как-то в pdf или ещё в какой формат сохранить, чтобы можно было увидеть содержимое HTML странцы. Я задавал вопрос здесь но ненашёл где написать продолжение:) Буду рад любому ценному комментарию. class Program { static string url = "http://www.whatbrowser.org"; static int width = 960, height = 1380; static int count = 0; [STAThread] static void Main(string[] args) { Console.WriteLine("hi"); try { int number = 1000; for (int i = 0; i < number; i++) { var th = new Thread(obj => RunGenerateScreenshotThread((string)obj)); th.SetApartmentState(ApartmentState.STA); th.Start(url); th.Join(); count++; } Console.WriteLine("All successfully completed!"); Console.ReadKey(true); } catch (Exception ex) { Console.WriteLine("Error: {0}", ex.ToString()); } } static void RunGenerateScreenshotThread(string url) { try { using (WebBrowser wb = new WebBrowser()) { // Set the size of the WebBrowser control wb.Width = width; wb.Height = height; //wb.DocumentCompleted += GenerateScreenshotCompleted; wb.Navigate(url); while (wb.ReadyState != WebBrowserReadyState.Complete) { System.Windows.Forms.Application.DoEvents(); } if (wb.DocumentTitle == "Navigation Canceled") Console.WriteLine("Natigated ERROR {0}", count); else Console.WriteLine("Natigated OK {0}", count); } } catch (Exception ex) { Console.WriteLine("Error: {0}", ex.ToString()); } finally { Application.ExitThread(); // Stops the thread } } }
Ответы
Ответ 1
1) нужно явно включить использования для своего приложения, прописав в реестре ключик. 2) что третий вопрос является ответом на второй. 3) а вот это сложный вопрос. сейчас практически все браузеры кушают очень много. upd Как бы я сделал. Отдельное приложение, которое получает два параметра - урл и куда сохранить (можно через параметры, можно через пайп). Его задача проста - загрузил, заскриншотил и отдал. Второе приложение в цикле запускает первое, передавая ему параметры (на первых порах это может быть обычный батник). плюсы: очень легко получается сделать для разных версий IE - просто два приложения, для одного прописан правильный webbrowser падения "скриншотерра" безопасно для основного приложения. так как приложение закрывается каждый раз, то это такой "костыль" против утечек. минусы: возможно некое падение скорости (но это ещё нужно проверить) нужно следить за дочерними процессамиОтвет 2
Браузер можно запускать в отдельном Thread + Task. Работает в WinForms и Console Application using System; using System.Windows.Forms; using System.Threading; using System.Threading.Tasks; static TaskNavigate (Uri url, Func callback) { var ts = new TaskCompletionSource (); var t = new Thread(() => { var wb = new WebBrowser() { AllowNavigation=true, ScriptErrorsSuppressed=true }; wb.DocumentCompleted += (s, e) => ts.SetResult(callback(wb.Document)); wb.Navigate(url); while (!ts.Task.IsCompleted) Application.DoEvents(); }); t.TrySetApartmentState(ApartmentState.STA); t.Start(); return ts.Task; } var t = Navigate(Uri("http://ru.stackoverflow.com"), doc => { return doc.Body.InnerHtml; // передается в t.Result }); Ответ 3
Есть еще одна проблема вот в этих строчках. while (wb.ReadyState != WebBrowserReadyState.Complete) { System.Windows.Forms.Application.DoEvents(); } В нормальном состоянии, при отсутствии событий программа засыпает и не расходует время процессора. Но ваш цикл так делать не умеет. Цикл обработки событий надо "крутить" через Application.Run, обязательно передав ему любую форму - тогда с процессорным временем все будет в порядке. Должно получиться примерно так: static void RunGenerateScreenshotThread(string url) { try { using (WebBrowser wb = new WebBrowser()) { // Set the size of the WebBrowser control wb.Width = width; wb.Height = height; wb.DocumentCompleted += (o, e) => Application.ExitThread(); wb.Navigate(url); Application.Run(new Form { Visible = false }); if (wb.DocumentTitle == "Navigation Canceled") Console.WriteLine("Natigated ERROR {0}", count); else Console.WriteLine("Natigated OK {0}", count); } } catch (Exception ex) { Console.WriteLine("Error: {0}", ex.ToString()); } } Наличие формы предотвращает немедленной выход из цикла обработки сообщений.
Комментариев нет:
Отправить комментарий