Question

I am facing a problem that Application.DoEvents() can solve. The problem is that WebBrowser suppose to navigate to a url asnychronously but it does't, and when I use Application.DoEvents() it solves that, I think this happens because the application handles some other events and doesn't deliver the events of the navigation properly.

I read a little about this method and I understand that method will cause the application to handle all the currents events. Now I am a bit concern because I used a cannon to kill an ant, Can someone tell me if what I did is worthwhile?

Was it helpful?

Solution

The Application.Dovents() method makes all pending messages processed. That can cause:

  1. Entering a code block twice before the current one finishes. (Let's assume that you navigate your browser with a button click. User clicks the button and while your code is waiting browser to copmlete the user clicked again. In that case Application.Doevents() will cause processing that method before stepping next line.)

  2. Interrupting critical codes. (Lets assume that you have a time consuming method and the user clicked close button. Your form will disappear but your code will continue to run. A real problem.

  3. Many more UnExpected results.

However I feel sometimes using this method is necessary and an easy solution like webbrowser which is difficult to use in multithreading (especially when its visible). If you have to use this method you should be sure that user and other things (timers, buttons, events vs) don't interrupt anything. For a detailed discuss:Use of Application.DoEvents()

OTHER TIPS

Yes, Application.DoEvents() solves this problem. The core issue is that WebBrowser is a heavily threaded component at its core. You can call its Navigate() method and it goes off doing its stuff without blocking your code, the method returns almost immediately.

The problem however is that at some point it has to run your DocumentCompleted event. Which is guaranteed to run on the thread on which you created the browser object. That's hard to do, your thread may well be busy doing something else. Like sitting in a loop, testing the ReadyState property. There is no mechanism to interrupt this loop and run the event handler.

So what you see is that the ReadyState property never changes and the DocumentCompleted event never fires. This is called deadlock, a very common curse of threaded code. Using DoEvents is the back-door, that "pumps the message loop". It allows the browser to break into your thread and fire the event. Which in turn updates the ReadyState property and lets you break out of the loop.

There's a Big Problem with DoEvents however. it isn't selective, it doesn't just limit itself to handling the message that allows the event to fire. It also dispatches other notifications, the kind that will crash your program. Like your user getting impatient with the slow web site and closing your form. That destroys the browser object but does not stop your loop. You are now testing the ReadyState property of a disposed browser. Kaboom!

You'll need to do this differently. It is never legal to block or hang up the UI thread in a loop, it is very prone to create deadlock. It is in fact forbidden by Microsoft guidelines for an STA thread. The workaround is simple, move whatever code you now have after the wait loop to the DocumentCompleted event handler. You might need to add some state variables to your class so that you know that the event signals completion of a particular web page or that the user is no longer interested in the result.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top