2009-02-24 7 views
17

Próbuję stworzyć program do klonowania wielu błędów w czasie przez interfejs sieciowy naszego systemu śledzenia wad. Jak mogę poczekać, zanim strona zostanie całkowicie załadowana, zanim przejdę dalej?C# jak czekać na zakończenie strony ładowania strony przed kontynuowaniem

//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. 
} 
+0

Mam ten sam problem, ale dla WebView. Masz pomysł, jak zaczekać, aż skończy się ładowanie? – yalematta

Odpowiedz

18

Spróbuj DocumentCompleted Event

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"); 
} 
+1

Czy ten kod oznacza, że ​​przeglądarka zawsze czeka na zakończenie przed wykonaniem poniższych poleceń? – AdorableVB

+0

Moja struktura gołej kości jest ładowana dość szybko, ale mam kod JS, który ładuje zawartość z DB do różnych DIV, a to zajmuje kilka sekund. Czy jest inne wydarzenie, które mogę wyzwolić? –

0

Jeśli używasz obiektu InternetExplorer.Application COM, sprawdzić właściwość readyState o wartości 4.

11

Sprawdź WatiN project:

Zainspirowany Watir rozwoju Watin rozpoczęty w grudniu 2005 r., aby umożliwić podobne testowanie aplikacji internetowych dla języków .Net. Od tego czasu WatiN stał się łatwym w obsłudze, bogatym w funkcje i stabilnym szkieletem. Watin jest opracowany w języku C# i ma na celu przybliżenie Państwu w łatwy sposób zautomatyzować testy z Internet Explorer i FireFox przy użyciu .NET ...

+1

Nie można się zgodzić na więcej. Byłem na obu drogach - weź swój własny koszmar kontroli WebBrowser i WatiN. WebBrowser może być synchroniczny, ale będziesz sobie później wdzięczny, jeśli pozwolisz WatiN wykonać pracę za ciebie. –

0

Zakładając "commit" element reprezentuje standardowy formularz przycisk submit następnie można dołączyć moduł obsługi zdarzeń dla zdarzenia webbrowsers nawigować.

28

Ten kod był dla mnie bardzo pomocny. Może to może być dla Ciebie również

wb.Navigate(url); 
while(wb.ReadyState != WebBrowserReadyState.Complete) 
{ 
    Application.DoEvents(); 
} 
MessageBox.Show("Loaded"); 
+2

Działa. Ale obciążenie procesora wzrośnie o "podczas" – Alex

+1

Możesz użyć Start-Sleep -Milliseconds 1000; w pętli while, aby uniknąć skoków procesora, ale wywołanie Qintins DocumentCompleted jest bardziej poprawne. – 79E09796

+1

@ jitbit- jak na tym świecie zorientowałeś się, że obciążenie procesora wzrośnie? Chodzi mi o to, co sprawiło, że to rozumiesz? – xameeramir

15

Najlepszym sposobem, aby to zrobić bez blokowania wątku UI jest użycie ASYNC i czekają wprowadzony w .NET 4.5.
Możesz wkleić to w swoim kodzie, wystarczy zmienić przeglądarkę na swoją nazwę przeglądarki. ten sposób Twój wątek czeka stronę, aby załadować, jeśli nie robi się na czas, zatrzymuje się oczekiwania i kod nadal działa:

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); 
     } 
    } 

I można go używać tak, ze w sposób asynchroniczny lub w przypadku kliknięcia przycisku, po prostu zrobić to aSYNC:

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. 
} 
+4

Wierzę: "if (Browser.Task.IsCompleted) return; PageLoaded.SetResult (true);" powinno być "if (PageLoaded.Task.IsCompleted) return; PageLoaded.SetResult (true);" –

6

metoda Zadanie pracował dla mnie, z wyjątkiem Browser.Task.IsCompleted musi zostać zmieniona na PageLoaded.Task.IsCompleted.

Niestety nie dodałem komentarza, ponieważ potrzebuję lepszej reputacji, aby dodawać komentarze.

-1

Po obejrzeniu niektórych z powyższych odpowiedzi, znalazłem wspólną wadę. Nie możesz uniwersalnie zastosować żadnego z powyższych rozwiązań. Jest to najlepszy sposób, aby przejść:

private void let_Load(string url) 
    { 
     // Waits for page to load 
     // If page doesn't load in 10 seconds, the while loop is exited with error 
     Stopwatch s = new Stopwatch(); 
     s.Start(); 
     while (url != webbrowser1.Url.ToString()) 
     { 
      Application.DoEvents(); 
      if (url == webbrowser1.Url.ToString()) 
       break; 
      if (s.Elapsed > TimeSpan.FromSeconds(9.9)) 
       { 
       richTextBox.Text = "Error: Page is unable to Load."; 
       break; 
       } 
     } 
    } 

Teraz wszystko co trzeba zrobić, to wywołać funkcję i przekazać adres URL, który trzeba załadować! Ponadto, ze względu na stoper, Twój kod nie zostanie zerwany, jeśli strona nie zostanie załadowana lub wystąpił jakiś błąd wejściowy. Kod automatycznie przestanie się zapętlać po 10 sekundach.

// Short Example 
webbrowser1.Navigate("http://twitter.com"); 
let_load("http://twitter.com"); 

Szybka uwaga: upewnij się, że przeglądarka ma już w niej adres URL. Wystarczy ustawić adres URL we właściwościach, aby załadował się po uruchomieniu aplikacji.

2

idk dlaczego, ale kod yuna i bnl zawiodły w poniższym przykładzie;

Pierwsza czeka na zakończenie., Ale druga z invokemember ("submit") didnt. invoke działa. ale ReadyState.Complete działa jak skompletowane przed NAPRAWDĘ zakończone:

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; 

jak naprawić tę niechcianą sytuację;

button1_click(){ 
     wb.Navigate("site1.com"); 
     waitWebBrowserToComplete(wb); 

     wb.Document.GetElementById("input1").SetAttribute("Value", "hello"); 
     //submit does navigation 
     wb.Document.GetElementById("formid").InvokeMember("submit"); 
     waitWebBrowserToComplete(wb); 
     // this actually waits for document Compelete. worked for me. 

     var processedHtml = wb.Document.GetElementsByTagName("HTML")[0].OuterHtml; 
     var rawHtml = wb.DocumentText; 
} 


//instead of checking readState . we get state from DocumentCompleted Event via bool value 
bool webbrowserDocumentCompleted = false; 
public static void waitWebBrowserToComplete(WebBrowser wb) 
{ 
    while (!webbrowserDocumentCompleted) 
    { 
     Application.DoEvents(); 
    } 
    webbrowserDocumentCompleted = false; 
    } 

    form_load(){ 
    wb.DocumentCompleted += (o, e) => { 
     webbrowserDocumentCompleted = true; 
     }; 
    } 
0
while (true) 
     {//ie is the WebBrowser object 
      if (ie.ReadyState == tagREADYSTATE.READYSTATE_COMPLETE) 
      { 
       break; 
      } 
      Thread.Sleep(500); 
     } 

Kiedyś tędy czekać aż załadowaniu strony.

Powiązane problemy