#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()); } } Наличие формы предотвращает немедленной выход из цикла обработки сообщений.
Комментариев нет:
Отправить комментарий