Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>I thought I should summarize some of the discussion in the comments into an answer.</p> <p>In Windows programming, you should never try to manipulate a GUI control from a background thread, as doing so can cause your program to deadlock . This means only the main thread should ever touch elements of the GUI. (Technically, what matters is which thread created the control, but it's not common to create controls in background threads).</p> <p>This requirement is detailed in <a href="http://flounder.com/workerthreads.htm" rel="nofollow noreferrer">Joe Newcomer's article on worker threads</a> (see "Worker Threads and the GUI II: Don't Touch the GUI").</p> <p>You are using <code>SendMessage</code> in your thread procedures. This causes the appropriate message handler for the target control to be invoked, but <em>in the thread that called <code>SendMessage</code></em>. In your case, that means the background threads run the message handlers and therefore update the progress bar and label.</p> <p>The alternative is to use <code>PostMessage</code>. This causes the message to be added to a queue to be processed by the main thread's message loop. When the main thread gets to run, it processes the messages in the order they were added to the queue, calling the message handlers itself. Since the main thread owns the windows, it is safe for it to update the controls.</p> <p>You should also beware that <code>SuspendThread</code> and <code>ResumeThread</code> are tricky to get right. You might want to read <a href="http://flounder.com/workerthreads.htm#Pausing%20a%20Thread" rel="nofollow noreferrer">this section</a> of Joe Newcomer's article, which describes some of the dangers.</p> <hr> <p>Tasks like this are often better achieved by using a <a href="http://www.functionx.com/visualc/controls/timer.htm" rel="nofollow noreferrer">timer</a>. This is a mechanism for having the operating system notify your program when a particular amount of time has passed. You could implement this with a timer as below:</p> <pre><code>BEGIN_MESSAGE_MAP(CThreadingEx3Dlg, CDialog) ON_WM_DESTROY() ON_WM_TIMER() END_MESSAGE_MAP() void CThreadingEx3Dlg::OnTimer(UINT_PTR nTimerID) { static int progress = 0; if (nTimerID == 1) { m_ProgressBar.SetPos(progress); CString strStatus; strStatus.Format(_T("Processing item: %d"), progress); m_Static.SetWindowText(strStatus); progress++; if (progress &gt; end) // If we've reached the end of the updates. KillTimer(1); } } BOOL CThreadingEx3Dlg::OnInitDialog() { // ... initialize controls, etc, as necessary. SetTimer(1, 100, 0); } void CThreadingEx3Dlg::OnDestroy() { KillTimer(1); } </code></pre> <p>If you want both updates handled at the same time, they can use the same timer. If they need to happen at different times (such as one at a 100 ms interval and another at a 150 ms interval) then you can call <code>SetTimer</code> twice with different IDs. To pause the action, call <code>KillTimer</code>. To resume it, call <code>SetTimer</code> again.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload