Event weirdness in form_open and form_load (threading issues??)

R

Robbie

I'm experiencing some odd behavior with events. I have a form with two
WebBrowser controls: QuestionWebBrowser and AnswerWebBrowser. I use the
QuestionWebBrowser to simply display html I have stored as a string in a
database (i.e. no need for navigation). On the other hand, AnswerWebBrowser
does navigate to a URL. In isolation both tasks are trivial and work fine.
However, I run into problems trying to do both things at the same time. The
biggest problem is that I need to wait for QuestionWebBrowser to load a blank
page so that I have access to the .document.body.innerHTML property

After some debugging, I've determined the following. In Form_Load (where we
wait for a blank document to be loaded into QuestionWebBrowser but do nothing
with AnswerWebBrowser), the call to DoEvents inside the loop results in
AnswerWebBrowser_DocumentComplete being fired (as well as DownloadComplete
and NavigateComplete). However, this occurs BEFORE Form_Current, which means
AnswerWebBrowser.Navigate2 should NOT yet have been invoked by my code. I
verify this by placing Debug.Print statements in all of the event methods.
If I put a break point in the AnswerWebBrowser_DocumentComplete code, and
check the call stack, I see: AnswerWebBrowser_DocumentComplete, [ <Non-Basic
Code> ], Form_Load. Following Form_Load takes me to "DoEvents". Oddly, when
printing out the url in AnswerWebBrowser_DocumentComplete, it is the same one
that would be called in the Form_Current method. This cannot be cached,
since I have tried exiting the form on different records, but the printed url
is always the same as the one from the first record. What is firing this
event???????

Once the blank question document is loaded (i.e. questionLoaded = true after
being set in QuestionWebBrowser_DocumentComplete), Form_Current is invoked,
causing AnswerWebBrowser to navigate to the page that it mysteriously already
navigated to. This is problematic since if the page is blank, I need to
forward to the next record; hence, I forward two records instead of just 1.

I thought that maybe the Form_Current was actually getting called during the
DoEvent processing. However, my Debug.Print inside of Form_Current only
displays once--after AnswerWebBrowser_NavigateComplete has already been
invoked. Maybe threading issues prevent the I/O from being displayed? This
would mean the DoEvents causes Form_Current to be called (But I/O is blocked)
which in turns calls AnswerWebBrowser_DocuemntComplete (but somehow I/O is
allowed there???). Form_Current is then re-invoked, after Form_Load is
finished. Could this be possible? Doesn't seem likely, but if so, how do I
prevent it? Unfortunately, when I enclose the body of Form_Current with "If
questionLoaded Then ...", the problem persists and so this probably isn't the
issue. Similarly surrounding my AnswerWebBrowser_DocumentComplete code with
if (questionLoaded) doesn't work either. This points heavily to concurrency
issues.

Even more weird: when I move the code from Form_Load to Form_Open, the form
opens normally, despite the fact that the code get stucks in an infinite loop
doing the DoEvents (Apparently the DoEvents allows the screen to draw and
records to be changed, but nothing happens in my code, e.g. form_current
isn't ever invoked, etc.). Oddly enough, this means that questionLoaded
never gets set to true -- despite the fact that it does when this code is in
Form_Load.

I have finally found a workaround: I can set a flag inside of Form_Current
and check that flag in the body of my AnswerWebBrowser_DocumentComplete event
handler. It works, but I'm wondering if there is (a) a more principled
solution and (b) an explanation as to why the events are acting so oddly.

I think what I really need is a monitor or a semaphore!

Here is my code (without the workaround):

Option Compare Database
Option Explicit

Private questionLoaded As Boolean
Private current As Boolean

Private Sub AnswerWebBrowser_DocumentComplete(ByVal pDisp As Object, URL As
Variant)
' If current Then
Debug.Print "AnswerWebBrowser_DocumentComplete!...pDisp = " & pDisp
& "; URL = " & URL
' End If
End Sub

Private Sub Form_Current()
QuestionWebBrowser.Document.body.innerHTML = [QuestionText]
Debug.Print "Form_Current()...Navigating to: " & answerUrl
AnswerWebBrowser.Navigate2 CStr(answerUrl)
End Sub

Private Sub Form_Load()
Debug.Print "Form_Load...Pre-Navigate"
questionLoaded = False
current = False
QuestionWebBrowser.Navigate2 "about:blank"
Debug.Print "Form_Load...Pre-DoEvent loop"
Do While Not questionLoaded
DoEvents
Loop
Debug.Print "Form_Load...Post-DoEvent loop"
End Sub

Private Sub QuestionWebBrowser_DocumentComplete(ByVal pDisp As Object, URL
As Variant)
questionLoaded = True
Debug.Print "QuestionWebBrowser_DocumentComplete...URL = " & URL
End Sub
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top