Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

DoEvents and Modal Forms = Hell

Status
Not open for further replies.

RaKKeR

Programmer
Nov 22, 2004
26
NL
Dear Programmers,

I'm experiencing a problem that is a real pain in the ass. As VB doesn't support threading, our project uses a VC++ dll that starts some thread for heavy load processes. This is how we wait for the thread to finish:

...
While WaitForSingleObject(ThreadID,200) = WAIT_TIMEOUT
DoEvents 'don't block the user interface
Wend
...

The problem is that when the DoEvents method gets called when the user clicked a button to open a modal form, the DoEvents method never returns till the user closes the form again (this is understandable, coz DoEvents tries to execute all pending window messages and the modal form waits for the user to close it).

Is there any other way to wait for the thread to end without blocking the user interface (getting rid of the doevents would cause this)?

Thx in advance,

RaKKeR
 
A keyword search in this forum should find a number of examples o how to shell and wait on a thread efficiently (and even threads on how to do threading with VB)
 
I haven't found any wait function yet where the DoEvents is NOT being used... Since the DoEvents method is causing serious problems, I hope someone can point me to a good alternative without telling me to search somewhere else coz that's what I've been doing for the last 2 days now...
 
Try looking for stuff about MsgWaitForMultipleObjects with QS_ALLINPUT (or a more limited QS_ of your choice) followed by a selective PeekMessage/TranslateMessage/DispatchMessage sequence (essentially your own DoEvents, but one that you can control)
 
That would indeed be a solution, but I want the user to be able to navigate through the GUI, even if the thread is running. So being selective in which messages to Dispatch is not an option here. Any other ideas? I was wondering if its possible to save the current call stack and than put it back later from within another event... Are there any win32 api calls to to this. The same way as interrupts are handled...
 
Then the DispatchMessage function will block, just like DoEvents blocks when a modal form is loaded...
 
Sure, but when the modal form is showing you don't want the GUI of the main form responding anymore (else why use a modal form). But you do want to be able to continue waiting on your C++ thread - so just run your wait event in another thread. And yes, you can do that in VB (as I hinted in my first post), as shown in my code in thread222-519374 (which is missing the proviso that the compiled version should be compiled to P-code and not to native).

 
which is missing the proviso that the compiled version should be compiled to P-code and not to native.
That's interesting, strongm. Why so, please?

Bob
 
Because it appears that p-code is thread-safe, whilst the native code is less so ... (Microsoft maintain that VB6 can't do threading at all, even though you could in VB5)

 
Thx all for your replies,

but my problem still remains. Is there any chance I can make DoEvents return? What I try to do is create a thread from a c++ dll and wait for that thread (by checking the returned ThreadID) while the GUI is still responsive by adding the DoEvents in the waiting loop. But when the user opens a modal form, DoEvents gets stuck itself (so the Thread seems to never end). Is there really no easy solution to this problem?

Thx in advance,

RaKKeR
 
I won't take no for an answer :)

There must be a way to suspend the current event handler and wait for the Thread within a Timer event and than when the Thread has ended give control back to the suspended event handler. I just need to find out how... Anyone?
 
You asked whether there was an easy solution, and seem to have rejected the waiting on a seperate thread that I proposed, so I don't know of any other way to do this in a single-threaded app that is showing a modal form ...
 
What if I put the waiting in a seperate thread? How could i possibly get back to the place in code where I started the waiting?

Lets say we have a lengthy nested procedure:

Sub Foo()
... 'lots of nested calls
...
.......'start a thread
.......'start waiting for thread
.......'how can I get back here when waiting for thread ended?
...
... 'lots of nested calls
End Sub
 
Maybe you could try something with a callback function

Greetings,
Rick
 
You're missing my point. You'd have to do a minot bit of redesign, and then

Sub AsynchronousProcedureThread()
'start waiting on our VC++ DLL, probably using MsgGetMultipleObjects
'Do what ever it is we need to do when we get notification that VC++ thread has finished, i.e from your code
...
... 'lots of nested calls

End Sub

Sub Foo
... 'lots of nested calls
...
....... ' Spawn AsnchronousProcedureThread in another thread
End Sub
 
And what if the variables that are used in de spawned thread are dependent on the state of the function that spawns the thread. I would not call it a "little" redesign...

Let me explain in more detail:

Code:
Public Function Function4() As Whatever
   ...
   'do something that takes a very long time
   ...
End Function

Public Function Function3() As Whatever
   ...
   ret = Function4()
   'do something with return value
   ...
End Function

Public Function Function2() As Whatever
   ...
   ret = Function3()
   'do something with return value
   ...
End Function

Public Function Function1() As Whatever
   ...
   ret = Function2()
   'do something with return value
   ...
End Function

Public Sub Timer1_Timer()
   ...
   ret = Function1()
   ...
End Sub

Now Tell me how can I put Function4 in a Thread without doing a "little" redesign?

 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top