我想暂停执行我的线程,直到通过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#正确地处理这样的程序,并且会重视一些建议!
答案 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