【问题标题】:WebBrowser Threads don't seem to be closingWebBrowser 线程似乎没有关闭
【发布时间】:2014-07-09 06:43:20
【问题描述】:

我正在使用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;
        }

    }
}

任何建议将不胜感激。

谢谢。

【问题讨论】:

  • 当网络浏览器将我的电脑变成烤面包机时,这通常是 JavaScript 失控的原因。 (一些 Flash 插件也是罪魁祸首。)通过在您放弃页面时停止来确保您的 JS 正在做它需要做的事情。
  • 这是一个 WPF 应用程序,一个 winform 应用程序,一个没有任何 UI 的应用程序,还是什么?
  • @Servy:我在文件顶部看到using System.Windows.Forms;,所以除非 OP 对项目做了一些奇怪的事情,否则它可能是 WinForms。
  • @PaulSasik 即访问WebBrowser 类本身。问题是这是否是他项目中唯一的 winform 代码,或者这是否是实际 Windows 窗体应用程序的一小部分。
  • 我正在通过在控制台中运行它来测试它,但我实际上是在尝试在 MVC 项目中运行它。

标签: c# javascript multithreading webbrowser-control


【解决方案1】:

WebBrowser 专门设计用于在 Windows 窗体项目中使用。它不是为在 Windows 窗体项目之外使用而设计的。

除其他外,它专门设计用于使用应用程序循环,几乎所有桌面 GUI 应用程序都存在这种循环。你没有这个,这当然会给你带来问题,因为浏览器利用它来实现基于事件的编程风格。

对碰巧正在阅读本文并且实际上正在创建 Winform、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;
}

【讨论】:

  • 感谢 Servy,我不知道这一点,这似乎正在工作。
  • @servy,它在Application.Run() 出现错误并出现此错误:An unhandled exception of type 'System.InvalidOperationException' occurred in System.Windows.Forms.dll Additional information: Starting a second message loop on a single thread is not a valid operation. Use Form.ShowDialog instead.,我该如何解决这个问题?
  • @Root125 如果您已经有一个正在运行的消息循环,那么您没有理由再创建一个。您只需要创建 webbrowser 并像使用 webbrowser 的大多数典型用法一样使用它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-11
  • 1970-01-01
  • 1970-01-01
  • 2015-09-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多