Click to See Complete Forum and Search --> : Worker thread cannot change the cursor
John E
April 8th, 2004, 12:35 PM
Here's a strange one.... At some point, my app displays a dialog box with OK & CANCEL buttons and a progress bar. If the user presses OK, it starts a lengthy process which is done in a worker thread. Whilst this is all going on the progress bar gets updated. All simple enough.... If the user wants to quit, he can press CANCEL - but depending on how much of the process has already been done, cancelling can take from 5 - 10 seconds during which, nothing is happening with the progress bar.
To give the user some feedback I decided to display a wait cursor. However, I can't make the worker thread change the cursor! I tried the simple option first (CWaitCursor) and I also tried using Windows API calls - i.e.
HCURSOR prevCursor, waitCursor = LoadCursor(NULL, IDC_WAIT);
SetClassLong(hWnd, GCL_CURSOR, (long)waitCursor));
prevCursor = ::SetCursor(waitCursor);
...but no way will the worker thread change the cursor!! If I put the same code into the dialog's main thread, I can change the cursor there (i.e. before starting the thread) but that isn't what I need.
Has anyone else noticed this oddity with a worker thread :confused:
Andreas Masur
April 8th, 2004, 12:41 PM
[Moved thread]
TheCPUWizard
April 8th, 2004, 01:04 PM
Only the UI thread can/should address UI issues, THIS INCLUDES the cursor.
Change the cursor in the UI thread before sending the request to the worker thread.
Change it back when the UI thread has been notified that the worker thread is complete/dead.\
John E
April 8th, 2004, 01:20 PM
Thanks for the suggestion but I can't really do it that way because the cursor needs to change while the worker thread is actually running. I wondered about sending a message to the UI thread though. Do you think it's worth trying?
John E
April 8th, 2004, 01:23 PM
Or alternatively, maybe I should create a UI thread for the long task instead of a worker thread. That way, it would have its own msesage loop anyway...
John E
April 8th, 2004, 01:25 PM
Hmm... which raises another point. Can a worker thread even send messages?? I know it can't receive them but I never thought before about whether or not it can send them....
TheCPUWizard
April 8th, 2004, 02:18 PM
Originally posted by John E
Or alternatively, maybe I should create a UI thread for the long task instead of a worker thread. That way, it would have its own msesage loop anyway...
The thread needs to be the thread that created the controls. In general there should only be one UI thread in a process [the exception being multiple independant windows].
Simple solution....have the worker thread post a message to the UI thread (as you aluded to).
A better architecure (if this is going to be a large project) may be to isolate all of these issues in a coordinator class that executes in both thread domains....but that gets a little complicated....
MrViggy
April 8th, 2004, 06:56 PM
Originally posted by John E
If the user wants to quit, he can press CANCEL - but depending on how much of the process has already been done, cancelling can take from 5 - 10 seconds during which, nothing is happening with the progress bar.
To give the user some feedback I decided to display a wait cursor.How is your worker thread getting the message to "cancel"? I'm assuming that you're trapping the "Cancel" button press in the GUI thread. You can't change the cursor then? Right before cancelling the worker thread?
Viggy
TDM
April 8th, 2004, 09:01 PM
Originally quoted by John E
Can a worker thread even send messages??
Yes, they can send messages.
TDM
John E
April 9th, 2004, 02:27 AM
Originally posted by MrViggy
How is your worker thread getting the message to "cancel"? I'm assuming that you're trapping the "Cancel" button press in the GUI thread. You can't change the cursor then? Right before cancelling the worker thread?Thanks Viggy. I did think of that but in fact, it's slightly more complicated than I described. The processing is done in chunks and when the user presses CANCEL, the program has to finish the chunk it's currently processing. It then puts up a message saying "Cancelling - please wait..." - and that's the point where I'd ideally like to display the wait cursor.
In fact, I realised later that the worker thread sends a message to the main thread anyway, to dislpay the "Cancelling..." message so I can easily send another one to change the cursor. I was just a bit baffled as to why the worker thread couldn't do this directly. I'd assumed that any thread should be capable of doing anything the processor can do - but obviously, it's not quite that simple!
Have a good easter, everyone....
Andreas Masur
April 9th, 2004, 05:29 AM
Originally posted by John E
Can a worker thread even send messages??
Take a look at the following FAQ (http://www.codeguru.com/forum/showthread.php?s=&threadid=231250)...
MikeAThon
April 14th, 2004, 08:01 PM
(You might have solved this already, but....)
The documentation for CWaitCursor indicates that the hourglass will show only during processing of a single message. So, if you're in your UI thread and the worker has just signaled that it's cancelling, and your UI thread shows a CWaitCursor, then in the very next message processed by the UI thread, the hourglass will disappear.
Code Project has a class called CPersistentWaitCursor that might help. See http://www.codeproject.com/dialog/persistentwaitcursor.asp
-Mike
John E
April 28th, 2004, 03:20 AM
Sending a message to the UI thread solved the problem.
codeguru.com
Copyright WebMediaBrands Inc., All Rights Reserved.