c++ - 我的 'show progress thread' 计数时不运行

标签 c++ multithreading winapi model-view-controller mfc

我有一个执行冗长处理的线程。当我等待线程完成时,我启动了另一个“显示进度”线程,它简单地来回切换位图以显示程序正在处理数据。令我惊讶的是,这种方法根本不起作用。

我的“show progerss”线程只是在主要事件开始时停止更新(=运行),并在该事件结束时开始更新。这几乎与我想要的相反!我是否应该因为 WaitForSingleOBject 大部分时间处于等待状态并短暂唤醒而预料到这种行为?

 // This is the main thread that does the actual work
 CWinThread* thread = AfxBeginThread(threadDoWork, this, THREAD_PRIORITY_LOWEST, 0, CREATE_SUSPENDED );
         thread->m_bAutoDelete = FALSE;
         thread->ResumeThread();

// before I start to wait on the above thread, I start this thread which will toggle image to show application is processing
 AfxBeginThread(ProgressUpdateThread, &thread_struct_param, THREAD_PRIORITY_NORMAL, 0 );

 // wait for the main thread now.
 DWORD dwWaitResult = WaitForSingleObject( thread->m_hThread, INFINITE );

 DWORD exitCode;
 ::GetExitCodeThread( thread->m_hThread, &exitCode );
 delete thread;

 // This thread toggles image to show activity 
 UINT ProgressUpdateThread(LPVOID param) 
 {
     CEvent * exitEvent = ((mystruct *)param)->exitEvent;
     MyView *view ((mystruct *)param)->view;

     int picture = 0;

     do
     {
         waitResult =  WaitForSingleObject( exitEvent->m_hObject, 100);

         if (waitResult == WAIT_TIMEOUT)
         {

            picture = toggle ? 1: 0;

             // invert
             toggle =  !toggle;

             View->Notify( UPDATE_IMAGE, picture );
         }
         else if (waitResult == WAIT_OBJECT_0)
         {
             return TRUE;
         }
     }
     while( 1);
 }

我的解决方案中的另一个考虑因素是我不想触及实际的“DoWork”线程代码,这也是我使用单独线程更新 GUI 的原因。我能让这种方法奏效吗?更新 GUI 可靠的唯一方法是从实际的“DoWork 线程本身”更新它吗?

我确实想澄清一下,如果应用程序处于空闲状态,我的“显示进度”线程可以完美地完成工作,但是如果我启动工作线程操作(以较低的线程优先级),更新 gui 线程只会停止运行并仅恢复当工作人员完成时。

我正在使用 Windows 7。

最佳答案

您的设计完全错误,而且对于您的尝试来说过于复杂。尝试更像这个更简单的解决方案:

bool toggle = false;

VOID CALLBACK updateProc(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
{
    int picture = toggle ? 1: 0;
    toggle = !toggle;
    View->Notify( UPDATE_IMAGE, picture );
}

CWinThread* thread = AfxBeginThread(threadDoWork, this, THREAD_PRIORITY_LOWEST, 0, CREATE_SUSPENDED );
thread->m_bAutoDelete = FALSE;
thread->ResumeThread();

UINT_PTR updateTimer = SetTimer(NULL, 0, 100, updateProc);

do
{
    DWORD dwWaitResult = MsgWaitForMultipleObjects(1, &(thread->m_hThread), FALSE, INFINITE, QS_ALLINPUT );
    if (dwWaitResult == WAIT_OBJECT_0)
        break;

    if (dwWaitResult == (WAIT_OBJECT_0+1))
    {
        MSG msg;
        while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        } 
    } 
}
while (true);

KillTimer(NULL, updateTimer);

DWORD exitCode;
::GetExitCodeThread( thread->m_hThread, &exitCode );
delete thread;

如果你不想为计时器使用一个独立的过程,你可以调整 SetTimer() 的参数让它发送 WM_TIMER 消息到一个 HWND 您选择的,然后根据需要在该窗口的消息过程中进行 UI 更新。不过,您仍然需要消息循环来发送定时器消息。

另一种方法是根本不进行任何等待。启动工作线程后,继续处理其他事情,并让工作线程在完成工作后通知主 UI 线程。

关于c++ - 我的 'show progress thread' 计数时不运行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18296732/

相关文章:

C++ Smooth player - 墙壁 - 碰撞(靠墙滑动)

c - 在 WIN32 中的 "BUTTON"类窗口上显示位图

c - 如何使用 cl 编译 Window API 程序?

c++ - 模板类静态在最终二进制文件中是否在共享库中以不同方式实例化?

c++ - 在 C++ 中执行一次序列的最佳方式

c++ - 在特定位置用元素填充数组

c# - 我的程序如何知道 Windows 已重新启动以进行更新

c - 使用线程的状态菜单

java - 如果任何线程中发生异常,则中断所有线程

c++ - 获取错误 : 'mutex' in namespace 'std' does not name a type in MinGW mysys prompt