等待WebBrowser ajax内容

时间:2010-09-25 16:16:02

标签: c# .net multithreading browser

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

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

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

然而,我对此的尝试失败了,我会重视我应该如何解决这个问题。我想只需调用new Thread(() => { Browser.Navigate(url); });的新线程就可以了,但是这样做之后,什么都没有加载,Browser.ReadyState仍然是'未初始化'。我认为我误解了如何使用C#正确地处理这样的程序,并且会重视一些建议!

4 个答案:

答案 0 :(得分:7)

以下内容应该有效,

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

以上对我有用......

答案 1 :(得分:6)

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

答案 2 :(得分:0)

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

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

答案 3 :(得分:0)

您不应调用Thread.Sleep,因为它将阻塞UI线程。

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

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