【问题标题】:Access Violation when using WebBrowser in multiple threads在多个线程中使用 WebBrowser 时访问冲突
【发布时间】:2017-02-16 20:17:02
【问题描述】:

我在多个线程中使用 WebBrowser,但是,在一些执行(从 50 到 10000+)之后,我得到了访问冲突异常。

相关部分代码:

开始线程:

    var thread = new Thread(() =>
    {
        ProcessingThread();
    });
    thread.SetApartmentState(ApartmentState.STA);
    thread.Start();

处理线程:

void ProcessingThread()
{
    WebBrowser webBrowser = new WebBrowser();
    webBrowser.ScriptErrorsSuppressed = true;
    while (!Shutdown)
    {
        string htmlstring = GetHTMLString();
        webBrowser.DocumentText = htmlstring;
        webBrowser.Document.OpenNew(true);
        webBrowser.Document.Write(htmlstring);
        webBrowser.Refresh();
        HtmlDocument doc = webBrowser.Document;

        //Do Work
    }
}

通常有 2 到 8 个这样的线程同时运行。

我经常遇到访问冲突

webBrowser.Document.OpenNew(true);

我已经阅读了许多类似的问题,但找不到我的问题的解决方案。

我想弄清楚异常的原因和解决方法。

到目前为止,我正在使用 WinForms 和 Visual Studio 2015 Update 3。

异常字符串:

抛出异常:“System.AccessViolationException”在 System.Windows.Forms.dll

我注意到的另一件事是,我使用的 .NET 版本越高,上面的线程在抛出异常之前设法执行的次数就越少。

例如,从我尝试运行它的十次开始,它在 .NET 4.5 上执行 1000 到 10000 次(我所做的所有测试的绝对最大值,通常最大值约为 5000 次),在 .NET 4.5 上执行 70 到 1500 次。 NET 4.6.1。

我试过了:

  • 使用本机代码调试选项,但仍指相同 线。
  • 更改平台目标而没有任何明显的结果。目前,它是 x86。
  • 打开和关闭代码优化。
  • 在没有调试器的情况下运行。
  • 将目标框架更改为无结果。目前是 .NET 4.5.2。
  • 在另一台机器上运行/调试应用程序。

我也知道 WebRequest、WebClient 和另外关于 HMTLAgilityPack,但我使用 WebBrowser 来支持它的 Javascript。

【问题讨论】:

  • 愚蠢的问题:为什么你需要在不同的线程中使用 2-8 个浏览器?我真的很好奇。
  • @FrancisLord,正在解析 HTML。其中一些使用 JavaScript 生成必要的数据,而使用 WebBrowser 是我能想到的获取数据的唯一方法。当然,我可以尝试使用不同的浏览器(例如 awesomium),但除非在此任务中必要,否则我真的不想使用 3rd 方工具,而且我真的很想知道当前访问冲突异常有什么问题。也应该可以在表单上放置多个 WebBrowser 并使用它们 - 但我认为这可能比我现在所做的更糟糕。
  • 您是否尝试将线程设置为 MTA 而不是 STA?
  • 根据我在网上快速搜索的内容,这基本上应该是您破坏了线程的一些 COM 合同,或者来自非托管代码中的访问冲突(您对此无能为力)跨度>
  • 您可能想看看这里所说的内容,这可能会对您有所帮助:stackoverflow.com/a/4156000/4064630。 TLDR:将线程设置为 STA 意味着您必须遵守 COM+ 设置的一些规则,否则,我相信您会得到 AccessViolation。那个或 WebBrowser 在非托管代码中引发错误,在 .net 中作为 AccessViolation 冒泡

标签: c# multithreading exception webbrowser-control access-violation


【解决方案1】:

就我而言,可行的解决方案是使用方法上的System.Runtime.ExceptionServices.HandleProcessCorruptedStateExceptions 属性来处理访问冲突异常。

经过一些测试,我发现只需捕获异常并重试引发异常的相同方法即可,因为执行继续正常,没有任何意外异常。

我已经在超过 100000 次执行中对其进行了测试,所以我认为它是通过的。

我写这篇文章是因为它在这种情况下对我来说是一种解决方案,并且可能对其他人有用,但是,我没有将其标记为已回答,因为我仍然不明白为什么会出现异常以及是否存在异常处理或防止这种情况的更好方法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多