My application may take a while to connect to a database. This connection is made with a single library function call, i.e. I cannot put progress updates in there and make callbacks or something similar.
My idea was to create a dialog with a progress bar in a separate thread before connecting to the DB. This dialog will continually change the progress status with CProgressCtrl::StepIt()
so the user sees something happening.
After that dialog is set up and doing its thing I want to call the DB connection function from the main thread.
After the connection function completed, I want to stop the progress bar thread.
Let me paint a picture:
CMyApp:: ProgressThread
InitInstance() .
| .
| .
+-Create Dialog-+
| |
| Animate
Connect Progress
to Bar
DB |
| |
+-Destroy Dlg---+
| .
| .
Is that possible? If yes, how?
Maybe the whole thing would work using timers, too. Would probably be much simpler but I couldn't get that to work either.
CProgressCtrl::SetMarquee()
which might do exactly what I need but I can't use it because the application does not have Unicode support.Update 2
I got it working the way AlexEzh and Javier De Pedro suggested: Put the DB stuf into its own thread.
initially I had concerns about how error handling could be done but it's actually quite similar to how it was before.
true
.CMyDialog::Animate()
which calls CProgressCtrl::StepIt()
and then Sleep()
s a bit.false
when done.Disadvantage: Moving the mouse over the window doesn't work. It's invisible. Thus no cancel-button or other interactive dialog elements can be used. I can live with that, however.
Since you liked the diagram, here is how it now looks like:
CMyApp:: WorkerThread
InitInstance() .
| .
| .
Create Dialog .
| .
+-Start Thread--+
| |
| Connect
Animate to
Progress DB
Bar |
| |
+-Thread Ends---+
| .
Destroy Dlg .
| .
I hope this article about creating own-thread splash screen with progress bar could be helpful. I wrote it while solving the problem with thread locking at MFC message queue level.
It would still be safer to move the DB connection logic to the separate thread. With DB on the dialog thread, you will be able to repaint the progress bar but not other controls in the dialog.
AfxBeginThread
.CProgressCtrl
and call Create
, pass the dialog as the parent of the CProgressCtrl, use the marquee style for the progress control. In the Thread create a message waiting loop:
MSG msg;
while(GetMessage(&Msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
The message loop need to check a global flag to see if to exit the loop.
Have you tried to use SendMessage
with PBM_SETMARQUEE
instead of SetMarquee
. I've never tried myself but it should work.
In my opinion the easiest way to achive what you want to do is making both the ProgressBar and DB connection in the ui thread and using OnTimer to call StepIt
in the progress bar.
You can also create the progress bar in the ui thread and use a custom message for the working thread to modify the progress status.
Anyway, I agree with AlexEzh that the best way to do it is making the whole non-UI work in the working thread.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With