【问题标题】:Waiting for WebBrowser ajax content等待 WebBrowser ajax 内容
【发布时间】:2011-04-17 05:01:10
【问题描述】:

我想暂停线程的执行,直到通过 ajax 将特定的 div 加载到 WebBrowser 实例中。显然,我可以不断检查这个 div 的存在,例如:

while (Browser.Document.GetElementById("divid") == null) { Thread.Sleep(200); }

然而,让浏览器处于循环之间的线程休眠只会首先阻止浏览器实际加载内容。因此,我似乎需要在单独的线程中执行 Browser.Navigate 方法 - 然后我可以继续检查/等待 div 的存在,同时 WebBrowser 实例继续加载我要求它加载的 URL。

然而,我在这方面的尝试失败了,我会重视任何关于我应该如何去做的意见。我认为只需使用new Thread(() => { Browser.Navigate(url); }); 分派一个新线程就可以了,但是这样做之后,什么都没有加载,并且 Browser.ReadyState 保持为“未初始化”。我想我误解了如何使用 C# 正确处理这样的线程过程,并且会重视一些建议!

【问题讨论】:

标签: c# .net multithreading browser


【解决方案1】:

不要阻塞主线程的消息泵。由于浏览器是 STA 组件,如果您阻止消息泵,xmlhttprequest 将无法从后台线程引发事件。 您无法在后台线程中导航。 Webbrowser ActiveX 的 Windows 窗体包装器不支持从 UI 线程以外的其他线程进行访问。请改用计时器。

【讨论】:

  • 您能否详细说明计时器的方法?我们可以在触发 DocumentCompleted 事件之前添加 1 秒的延迟吗?
  • 不,但您可以启动一个计时器,然后在其滴答事件中解析文档,假设 ajax 操作在计时器滴答之前完成。完成解析后记得停止计时器。
【解决方案2】:

以下应该可以工作,

while (Browser.Document.GetElementById("divid") == null) 
{ 
    Application.DoEvents();
    Thread.Sleep(200); 
}

以上对我有用...

【讨论】:

  • 我也做过类似的实验,但最后还是用了姜生的方法。这似乎是更“正确”的方式。
  • 如果 div 没有完全加载怎么办?
【解决方案3】:

您可以在正文中找到一个文本,例如:

while (HtmlWindow.Document.Body.InnerHtml.Contains(some_text) == false)
{        
    Application.DoEvents();
    Thread.Sleep(200);
}

【讨论】:

    【解决方案4】:

    你不应该调用Thread.Sleep,因为它会阻塞 UI 线程。

    更好的解决方案是创建一个异步任务。在此任务中,您可以调用 Task.Delay,这不会干扰 UI。

    static async Task<IHTMLElement> WaitForElement(WebBrowser browser, string elementID, TimeSpan timeout)
    {
        long startTime = DateTimeOffset.Now.ToUnixTimeMilliseconds();
        var timeoutMS = timeout.TotalMilliseconds;
    
        // While the timeout has not passed...
        while (DateTimeOffset.Now.ToUnixTimeMilliseconds() - startTime < timeoutMS)
        {
            // Wait for 200ms
            await Task.Delay(TimeSpan.FromMilliseconds(200));
    
            // Check if the document contains the element
            var document = (HTMLDocument) browser.Document;
            var element = document.getElementById(elementID);
            if (element != null)
            {
                // Element found, stop looping
                return element;
            }
        }
    
        throw new Exception($"Element was not loaded after {timeoutMS} milliseconds");
    }
    

    上面的代码每 200 毫秒检查一次 DOM 以查看具有给定 ID 的元素是否存在。它还包含一个超时(例如 10 秒),以防元素因任何意外原因而永远不会加载。

    这是一个示例,展示了如何使用此函数从 AJAX 调用后添加到文档的文本字段中读取值:

    var input = (IHTMLInputElement) await WaitForElement(myBrowserControl, "input-id", TimeSpan.FromSeconds(10));
    var value = input.value; // Read the value of the input field
    

    【讨论】:

      猜你喜欢
      • 2016-01-01
      • 1970-01-01
      • 2011-11-09
      • 2018-04-11
      • 1970-01-01
      • 1970-01-01
      • 2010-12-17
      • 2018-01-16
      相关资源
      最近更新 更多