7

我有一个 for 循环:

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

webB是一个 webBrowser 控件并且i是一个 int。

我想等待浏览器完成导航。

但是,我发现了这个

  • 我不想使用任何 API 或插件
  • 如this answer中所建议,我不能使用其他void功能

有没有办法在 for 循环中等待?

4

7 回答 7

7

假设您托管在 WinFroms 应用程序中,您可以使用模式WebBrowser轻松有效地循环执行它。async/await尝试这个:

async Task DoNavigationAsync()
{
    TaskCompletionSource<bool> tcsNavigation = null;
    TaskCompletionSource<bool> 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<bool>();
        tcsDocument = new TaskCompletionSource<bool>();

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

现在,了解DoNavigationAsync异步执行很重要。以下是您如何调用它Form_Load并处理它的完成:

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

我在这里回答了一个类似的问题。

于 2013-08-19T02:43:36.950 回答
2

您不必使用其他void功能。只需lambda像这样使用:

webB.DocumentCompleted += (sender, e) =>
{
    // your post-load code goes here
};
于 2013-08-19T00:11:10.417 回答
1

正确的方法是使用事件。
在你的循环中,你怎么知道导航已经完成?也许你不在循环中,但它只是通过了一半......

此外,等待时循环称为忙等待,并且CPU 开销很大

为了在页面准备好时收到通知,同时保持 CPU 可用于其他东西,请按照@Jashaszun 的建议使用事件:

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...
}
于 2013-08-19T03:45:44.660 回答
1

在 for 循环中使用这个 while 循环。

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

这将等到 WebBrowser 完全加载页面。

于 2017-01-24T08:42:15.957 回答
0

尝试使用这样的任务:

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

希望我有所帮助。

于 2014-10-11T16:38:18.300 回答
0

要在线程中等待,您可以执行以下操作

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

不幸的是,它与导航完成时间无关。

于 2013-08-18T22:14:20.467 回答
0
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
于 2015-11-16T01:32:03.667 回答