¿Puedo esperar a que un navegador web termine de navegar, usando un bucle for?

Tengo un bucle for:

for (i = 0; i <= 21; i++) { webB.Navigate(URL); } 

webB es un control webBrowser e i es un int.

Quiero esperar a que el navegador termine de navegar.

Encontré esto , sin embargo:

  • No quiero usar ninguna API o complementos
  • No puedo usar otra función de void , como se sugiere en esta respuesta

¿Hay una manera de esperar mientras está en un bucle for?

Suponiendo que aloja WebBrowser en una aplicación WinFroms, puede hacerlo en un bucle de manera fácil y eficiente, utilizando un patrón async/await . Prueba esto:

 async Task DoNavigationAsync() { TaskCompletionSource tcsNavigation = null; TaskCompletionSource tcsDocument = null; this.WB.Navigated += (s, e) => { if (tcsNavigation.Task.IsCompleted) return; tcsNavigation.SetResult(true); }; this.WB.DocumentCompleted += (s, e) => { if (this.WB.ReadyState != WebBrowserReadyState.Complete) return; if (tcsDocument.Task.IsCompleted) return; tcsDocument.SetResult(true); }; for (var i = 0; i <= 21; i++) { tcsNavigation = new TaskCompletionSource(); tcsDocument = new TaskCompletionSource(); this.WB.Navigate("http://www.example.com?i=" + i.ToString()); await tcsNavigation.Task; Debug.Print("Navigated: {0}", this.WB.Document.Url); // navigation completed, but the document may still be loading await tcsDocument.Task; Debug.Print("Loaded: {0}", this.WB.DocumentText); // the document has been fully loaded, you can access DOM here } } 

Ahora, es importante entender que DoNavigationAsync ejecuta de forma asíncrona. Así es como lo llamarías desde Form_Load y manejarías su finalización:

 void Form_Load(object sender, EventArgs e) { var task = DoNavigationAsync(); task.ContinueWith((t) => { MessageBox.Show("Navigation done!"); }, TaskScheduler.FromCurrentSynchronizationContext()); } 

He respondido una pregunta similar aquí .

No tienes que usar otra función de void . Simplemente usa una lambda como tal:

 webB.DocumentCompleted += (sender, e) => { // your post-load code goes here }; 

Utilice este bucle while dentro del bucle for.

 while (webB.ReadyState != tagREADYSTATE.READYSTATE_COMPLETE) { Thread.Sleep(500); } 

Esto espera hasta que el WebBrowser cargue la página completamente.

Para esperar en un hilo puedes hacer algo como esto.

  System.Threading.Thread.Sleep(2000); //waits 2 seconds 

Desafortunadamente, no está vinculado con el tiempo de finalización de la navegación.

La forma correcta es usar los eventos.
En su bucle, ¿cómo puede saber que se ha completado la navegación? tal vez usted está fuera del circuito pero es sólo la mitad del camino …

Además, el bucle mientras se espera se denomina Ocupado en espera y es caro para la CPU .

Para recibir una notificación cuando la página esté lista, y mientras tanto mantenga la CPU disponible para otras cosas, use los eventos como @Jashaszun sugirió:

 void YourFunction() { //Do stuff... webB.DocumentCompleted += (sender, e) => { //Code in here will be triggered when navigation is complete and document is ready }; webB.Navigate(URL); //Do more stuff... } 

Intenta usar tareas como esta:

 for (i = 0; i <= 21; i++) { Task taskA = Task.Factory.StartNew(() => webB.Navigate(URL)); taskA.Wait(); } 

Espero haberte ayudado.

 Public Class Form1 Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load WebBrowser1.Navigate("stackoverflow.com/") End Sub Private Sub WebBrowser1_DocumentCompleted(ByVal sender As System.Object, ByVal e As System.Windows.Forms.WebBrowserDocumentCompletedEventArgs) Handles WebBrowser1.DocumentCompleted ------yourcode------ End Sub End Class