我正在使用WebBrowser
在网页上呈现javascript来抓取渲染的源代码,但是在多次加载页面后,CPU使用率达到了100%以及线程数。
我假设一旦网页呈现后线程没有正确关闭。我正在尝试打开浏览器,提取源代码,然后关闭浏览器并转到下一页。
我能够获得渲染的页面,但是这个程序在陷入困境之前并没有走得太远。我尝试添加wb.Stop()
,但这没有用。记忆似乎不是问题(保持在70%左右)。
这是我的源代码。 使用系统; 使用System.Collections.Generic; 使用System.Linq; 使用System.Text; 使用System.Threading.Tasks; 使用System.Windows.Forms; 使用System.Threading;
namespace Abot.Demo
{
// Threaded version
public class HeadlessBrowser
{
private static string GeneratedSource { get; set; }
private static string URL { get; set; }
public static string GetGeneratedHTML(string url)
{
URL = url;
Thread t = new Thread(new ThreadStart(WebBrowserThread));
t.SetApartmentState(ApartmentState.STA);
t.Start();
t.Join();
return GeneratedSource;
}
private static void WebBrowserThread()
{
WebBrowser wb = new WebBrowser();
wb.Navigate(URL);
wb.DocumentCompleted +=
new WebBrowserDocumentCompletedEventHandler(
wb_DocumentCompleted);
while (wb.ReadyState != WebBrowserReadyState.Complete);
//Application.DoEvents();
//Added this line, because the final HTML takes a while to show up
GeneratedSource = wb.Document.Body.InnerHtml;
wb.Dispose();
wb.Stop();
}
private static void wb_DocumentCompleted(object sender,
WebBrowserDocumentCompletedEventArgs e)
{
WebBrowser wb = (WebBrowser)sender;
GeneratedSource = wb.Document.Body.InnerHtml;
}
}
}
任何建议将不胜感激。
感谢。
答案 0 :(得分:1)
WebBrowser
专门用于从Windows窗体项目中使用。它不是设计用于Windows窗体项目之外的。
除此之外,它还专门设计为使用应用程序循环,它几乎存在于任何桌面GUI应用程序中。你没有这个,这当然会给你带来麻烦,因为浏览器会利用它来实现基于事件的编程风格。
快速了解未来的读者,他们正在阅读本文,并且实际上正在创建一个winforms,WPF或其他已经有消息循环的应用程序。不要应用以下代码。您应该只在应用程序中有一个消息循环。创建几个就是为噩梦设置自己。
由于您没有应用程序循环,您需要创建一个新的应用程序循环,指定一些代码在该应用程序循环中运行,允许它抽取消息,然后在获得结果时将其拆除。
public static string GetGeneratedHTML(string url)
{
string result = null;
ThreadStart pumpMessages = () =>
{
EventHandler idleHandler = null;
idleHandler = (s, e) =>
{
Application.Idle -= idleHandler;
WebBrowser wb = new WebBrowser();
wb.DocumentCompleted += (s2, e2) =>
{
result = wb.Document.Body.InnerHtml;
wb.Dispose();
Application.Exit();
};
wb.Navigate(url);
};
Application.Idle += idleHandler;
Application.Run();
};
if (Thread.CurrentThread.GetApartmentState() == ApartmentState.STA)
pumpMessages();
else
{
Thread t = new Thread(pumpMessages);
t.SetApartmentState(ApartmentState.STA);
t.Start();
t.Join();
}
return result;
}