C# как дождаться завершения загрузки веб-страницы перед продолжением
Я пытаюсь создать программу для клонирования нескольких ошибок одновременно через веб-интерфейс нашей системы отслеживания дефектов. Как я могу дождаться полной загрузки страницы, прежде чем продолжить?
//This is pseudo code, but this should give you an idea of what I'm trying to do. The
//actual code uses multi-threading and all that good stuff :).
foreach (string bug in bugs)
{
webBrowser.Navigate(new Uri(url));
webBrowser.Document.GetElementById("product").SetAttribute("value", product);
webBrowser.Document.GetElementById("version").SetAttribute("value", version);
webBrowser.Document.GetElementById("commit").InvokeMember("click");
//Need code to wait for page to load before continuing.
}
Ответов (11)11
Попробуйте DocumentCompleted
событие:
webBrowser.DocumentCompleted +=
new WebBrowserDocumentCompletedEventHandler(webBrowser_DocumentCompleted);
void webBrowser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
webBrowser.Document.GetElementById("product").SetAttribute("value", product);
webBrowser.Document.GetElementById("version").SetAttribute("value", version);
webBrowser.Document.GetElementById("commit").InvokeMember("click");
}
Зайдите в Selenium ( http://seleniumhq.org ) или WatiN ( http://watin.sourceforge.net ), чтобы сэкономить немного времени.
Я думаю, что событие DocumentCompleted элемента управления WebBrowser должно доставить вас туда, куда вам нужно.
Лучший способ сделать это без блокировки потока пользовательского интерфейса - использовать Async и Await, представленные в .NET 4.5.
Вы можете вставить это в свой код, просто изменив браузер на свое имя веб-браузера. Таким образом, ваш поток ожидает загрузки страницы, если он не загружается вовремя, он перестает ждать, и ваш код продолжает выполняться:
private async Task PageLoad(int TimeOut)
{
TaskCompletionSource<bool> PageLoaded = null;
PageLoaded = new TaskCompletionSource<bool>();
int TimeElapsed = 0;
Browser.DocumentCompleted += (s, e) =>
{
if (Browser.ReadyState != WebBrowserReadyState.Complete) return;
if (PageLoaded.Task.IsCompleted) return; PageLoaded.SetResult(true);
};
//
while (PageLoaded.Task.Status != TaskStatus.RanToCompletion)
{
await Task.Delay(10);//interval of 10 ms worked good for me
TimeElapsed++;
if (TimeElapsed >= TimeOut * 100) PageLoaded.TrySetResult(true);
}
}
И вы можете использовать это так, в асинхронном методе или в событии нажатия кнопки, просто сделайте его асинхронным:
private async void Button1_Click(object sender, EventArgs e)
{
Browser.Navigate("www.example.com");
await PageLoad(10);//await for page to load, timeout 10 seconds.
//your code will run after the page loaded or timeout.
}
код yuna и bnl не прошел в приведенном ниже случае;
неудачный пример:
1-й ожидает завершения. Но 2-й с invokemember ("submit") не сделал. вызывать работает. но ReadyState.Complete действует как Completed до того, как ДЕЙСТВИТЕЛЬНО завершится:
wb.Navigate(url);
while(wb.ReadyState != WebBrowserReadyState.Complete)
{
Application.DoEvents();
}
MessageBox.Show("ok this waits Complete");
//navigates to new page
wb.Document.GetElementById("formId").InvokeMember("submit");
while(wb.ReadyState != WebBrowserReadyState.Complete)
{
Application.DoEvents();
}
MessageBox.Show("webBrowser havent navigated yet. it gave me previous page's html.");
var html = wb.Document.GetElementsByTagName("HTML")[0].OuterHtml;
как исправить эту нежелательную ситуацию:
использование
public myForm1 {
myForm1_load() { }
// func to make browser wait is inside the Extended class More tidy.
WebBrowserEX wbEX = new WebBrowserEX();
button1_click(){
wbEX.Navigate("site1.com");
wbEX.waitWebBrowserToComplete(wb);
wbEX.Document.GetElementById("input1").SetAttribute("Value", "hello");
//submit does navigation
wbEX.Document.GetElementById("formid").InvokeMember("submit");
wbEX.waitWebBrowserToComplete(wb);
// this actually waits for document Compelete. worked for me.
var processedHtml = wbEX.Document.GetElementsByTagName("HTML")[0].OuterHtml;
var rawHtml = wbEX.DocumentText;
}
}
//put this extended class in your code.
//(ie right below form class, or seperate cs file doesnt matter)
public class WebBrowserEX : WebBrowser
{
//ctor
WebBrowserEX()
{
//wired aumatically here. we dont need to worry our sweet brain.
this.DocumentCompleted += (o, e) => { webbrowserDocumentCompleted = true;};
}
//instead of checking readState, get state from DocumentCompleted Event
// via bool value
bool webbrowserDocumentCompleted = false;
public void waitWebBrowserToComplete()
{
while (!webbrowserDocumentCompleted )
{ Application.DoEvents(); }
webbrowserDocumentCompleted = false;
}
}
Ознакомьтесь с проектом WatiN :
Вдохновленный Watir, разработка WatiN началась в декабре 2005 года, чтобы сделать подобное тестирование веб-приложений возможным для языков .Net. С тех пор WatiN превратился в простой в использовании, многофункциональный и стабильный фреймворк. WatiN разработан на C# и призван предоставить вам простой способ автоматизации тестов с помощью Internet Explorer и FireFox с использованием .Net ...