2009-02-24 64 views
17

Estoy intentando crear un programa para clonar varios errores a la vez a través de la interfaz web de nuestro sistema de seguimiento de defectos. ¿Cómo puedo esperar antes de que una página esté completamente cargada antes de continuar?C# cómo esperar a que una página web termine de cargarse antes de continuar

//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

Tengo el mismo problema pero para WebView. ¿Alguna idea de cómo esperar hasta que termine de cargar? – yalematta

Respuesta

18

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

¿Este código significa que el navegador web siempre esperará para completarse antes de ejecutar los comandos a continuación? – AdorableVB

+0

La estructura de mi página básica se carga bastante rápido, pero tengo el código JS que carga el contenido de un DB en diferentes DIV y eso lleva unos segundos. ¿Hay algún otro evento que pueda desencadenar? –

0

Si está utilizando el objeto COM InternetExplorer.Application, comprobar la propiedad ReadyState por el valor de 4.

11

Mira la WatiN project:

Inspirado por Watir desarrollo de WatiN comenzado en diciembre de 2005 para hacer un tipo similar de prueba de aplicación web posible para los lenguajes .Net. Desde entonces, WatiN se ha convertido en un marco fácil de usar, rico en características y estable. WatiN está desarrollado en C# y objetivo es ofrecer una manera fácil de automatizar sus pruebas con Internet Explorer y Firefox usando .Net ...

+1

No podría estar más de acuerdo. He recorrido las dos carreteras: lanzar pesadillas de control WebBrowser y WatiN. El WebBrowser se puede sincronizar, pero se lo agradecerá más adelante si deja que WatiN haga el trabajo por usted. –

0

Suponiendo que el elemento de "comprometerse" representa una forma estándar de botón de envío a continuación, se puede adjuntar un controlador de eventos para el evento webbrowsers Navigated.

28

Este código fue muy útil para mí. Tal vez podría ser para usted también

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

Trabajos. Pero la carga de la CPU se disparará en ese "mientras" – Alex

+1

Puede usar Start-Sleep -Milliseconds 1000; en el ciclo while para evitar el pico de CPU, pero la devolución de llamada Qintins DocumentCompleted es más correcta. – 79E09796

+1

@ jitbit- ¿cómo en este mundo te diste cuenta de que la carga de la CPU se disparará? Quiero decir, ¿qué te hizo entender esto? – xameeramir

15

mejor manera de hacer esto sin bloquear el hilo de interfaz de usuario es el uso asíncrono y esperar introdujo en .NET 4.5.
Puede pegar esto en su código simplemente cambie el navegador al nombre de su navegador web. De esta manera, el hilo espera la página para cargar, si se duerma en el tiempo, se detiene en espera y su código continúa ejecutándose:

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

Y usted puede utilizar de esta manera, con en un método asíncrono , o en un evento de clic de botón, simplemente hacer que sea asíncrono:

método de tareas
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

Creo: "if (Browser.Task.IsCompleted) return; PageLoaded.SetResult (true);" debería ser "if (PageLoaded.Task.IsCompleted) return; PageLoaded.SetResult (true);" –

6

trabajado para mí, excepto Browser.Task.IsCompleted tiene que ser cambiado a PageLoaded.Task.IsCompleted.

Lo siento, no agregué ningún comentario, es porque necesito una mayor reputación para agregar comentarios.

-1

Después de ver algunas de las respuestas anteriores, encontré un error común. No puede utilizar ninguna de las soluciones anteriores universalmente. Este es el mejor camino a seguir:

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

Ahora todo lo que necesita hacer es llamar a la función y pasa la dirección URL que necesita para cargar! Además, debido al cronómetro, su código no se romperá si su página web nunca se carga o si hay algún tipo de error de entrada. El código dejará de funcionar automáticamente después de los 10 segundos.

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

Nota rápida: Asegúrese de que el navegador web ya tenga una url. Simplemente configure la URL en propiedades para que se cargue cuando ejecute su aplicación.

2

idk por qué pero el código de yuna y bnl falló en el caso siguiente;

1ra espera para completado.pero, 2º con el miembro de invocación ("enviar") no. invocar funciona pero ReadyState.Complete actúa como su completadas antes de su REALMENTE completado:

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; 

cómo solucionar esta situación no deseada;

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

que utilizan esta forma que esperar hasta la página se carga.

Cuestiones relacionadas