Jack
Jack

Reputation: 16724

Why getting webBrowser's state only works if using another thread?

I want to wait until browser.ReadyState == WebBrowserReadyState.Complete. There's DocumentCompleted Webbrowser's event, but if the page is being loaded by using AJAX it does fire when the HTML is ready, the missing contentes being loaded by ajax isn't available at this time. My first ide was:

int[] myFunction() {

  int[] values;

 while (browser.ReadyState != WebBrowserReadyState.Complete) {
         Application.DoEvents();
  }
             values = get_values_from_browser();
  return values;
}

it doesn't works return soon than it should and I get wrong value in the array, for example, all the elements are the same. However, if I use a Timer it does Works (I get correct values in the array) but I can't return from the function because I don't know when return from function.

The timer is:

System.Windows.Forms.Timer timer1 = new System.Windows.Forms.Timer();
     int[] myFunction() {

      int[] values;
      timer1.Interval = 1000;
                timer1.Tick += new EventHandler(delegate(object o, EventArgs ea)
                    {
                            if (browser.ReadyState == WebBrowserReadyState.Complete)
                            {
                                timer1.Stop();
                                values = get_values_from_browser();
                            }
                    });
                timer1.Start();
          return values;
    }

So my question is: Why it does works using a new thread (the System.Windows.Forms.Timer) but doesn't with the while loop in the main thread? any Thread.Sleep(x) in the main case will make it work.

Upvotes: 1

Views: 488

Answers (2)

noseratio
noseratio

Reputation: 61666

An AJAX page is non-deterministic. E.g., its JavaScript logic might be using its own timers to make XHR requests, in which case browser.ReadyState wouldn't be a reliable indicator of any pending activity. Moreover, I'm not even sure XHR request themselves count towards browser.ReadyState. WebBrowser.IsBusy is more likely to account for that. On a side note, don't use Application.DoEvents(), in most cases it's a pure evil.

To solve the problem, you could use asynchronous polling. I've answered a similar question with some sample code here:

https://stackoverflow.com/a/20934538/1768303.

Upvotes: 1

John Earnshaw
John Earnshaw

Reputation: 331

In your first method you're doing:

int[] myFunction() {

   int[] values;

   while (browser.ReadyState != WebBrowserReadyState.Complete) {
        values = get_values_from_browser();
        Application.DoEvents();
   }

   return values;
}

shouldn't this be:

int[] myFunction() {

   int[] values;

   while (browser.ReadyState != WebBrowserReadyState.Complete) {
       Application.DoEvents();
   }

   values = get_values_from_browser();
   return values;

}

Upvotes: 0

Related Questions