无论如何,我都无法通过线程更新此进度条

时间:2010-12-21 06:29:26

标签: windows multithreading winapi mingw

我有一个用C语言编写的Windows应用程序(使用gcc / MinGW)除了一些UI问题外,效果很好。一,我根本无法从一个线程获取进度条。事实上,我可能无法获得任何UI更新内容。

基本上,我有一个产生一些处理的衍生线程,并且从该线程我尝试更新主线程中的进度条。我尝试使用PostMessage()到主hwnd,但没有运气,即使我可以做其他事情,如打开消息框。但是,不清楚消息框是在线程内还是在主线程上调用。

以下是一些代码:

// in header/globally accessible
HWND wnd; // main application window
HWND progress_bar; //progress bar

typedef struct { //to pass to thread
    DWORD mainThreadId;
    HWND mainHwnd;
    char *filename;
} THREADSTUFF;


//callback function
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam){
    switch (msg){
        case WM_CREATE:{
            // create progress bar
            progress_bar = CreateWindowEx(
                0,
                PROGRESS_CLASS,
                (LPCTSTR) NULL,
                WS_CHILD | WS_VISIBLE,
                79,164,455,15,
                hwnd,
                (HMENU)20,
                NULL,
                NULL);

            SendMessage(progress_bar, PBM_SETSTEP, 1, 0 );
            SendMessage(progress_bar, PBM_SETPOS, 0, 0 );
            //test to make sure it actually works
            SendMessage(progress_bar, PBM_STEPIT, 0, 0 ); //works fine
            SendMessage(progress_bar, PBM_STEPIT, 0, 0 ); //works fine
            SendMessage(progress_bar, PBM_STEPIT, 0, 0 ); //works fine
            SendMessage(progress_bar, PBM_STEPIT, 0, 0 ); //works fine

            break;
        }

        case WM_COMMAND: {
            if(LOWORD(wParam)==2){ //do some processing in a thread

                //struct of stuff I need to pass to thread
                THREADSTUFF *threadStuff;
                threadStuff = (THREADSTUFF*)malloc(sizeof(*threadStuff));
                threadStuff->mainThreadId = GetCurrentThreadId();
                threadStuff->mainHwnd = hwnd;
                threadStuff->filename = (void*)&filename;
                hThread1 = CreateThread(NULL,0,convertFile (LPVOID)threadStuff,0,NULL);

            }else if(LOWORD(wParam)==5){ //update progress bar

                MessageBox(hwnd,"I got a message!", "Message",  MB_OK | MB_ICONINFORMATION);
                PostMessage(progress_bar,PBM_STEPIT,0,0);
            }
            break;
        }
    }
}

这一切似乎都运转正常。问题在于:

DWORD WINAPI convertFile(LPVOID params){

    //get passed params, this works perfectly fine
    THREADSTUFF *tData = (THREADSTUFF*)params;

    MessageBox(tData->mainHwnd,tData->filename,"File name",MB_OK | MB_ICONINFORMATION); //yep

    PostMessage(tData->mainHwnd,WM_COMMAND,5,0); //only shows message
    PostThreadMessage(tData->mainThreadId,WM_COMMAND,5,0); //does nothing
}

当我说“只显示消息”时,这意味着回调中的MessageBox()函数可以工作,而不是PostMessage()来更新进度条的位置。

如果我使用PostThreadMessage()向主线程的消息循环发送消息,我可以拦截它并启动MessageBoxes,这样它肯定有效。但是,即使我尝试以这种方式更新进度条。它仍然不会更新。

我错过了什么?

2 个答案:

答案 0 :(得分:1)

来自MSDN documentation for PBM_STEPIT

wParam
    Must be zero.
lParam
    Must be zero.

CLR_DEFAULT定义为0xFF000000L。如果您将代码更改为:

会发生什么
PostMessage(progress_bar, PBM_STEPIT, 0, 0);

答案 1 :(得分:1)

我怀疑问题在于你的消息循环。无论如何,有三件事:

  • 我认为发布PBM_STEPIT消息没有任何理由,只需发送即可。
  • 检查你的消息循环并确保你没有做像GetMessage那样愚蠢的事情(& msg,hwnd,... - 总是为GetMessage的hwnd参数传递NULL,否则将发送到其他窗口的消息永远不会被分派
  • WindowProc始终由Windows在正确的线程中调用。所以你可以将SendMessage或PostMessage直接从工作线程发送到进度控制来更新它。
第四点奖励:

  • MessageBox创建一个窗口,并在调用线程中运行其消息循环。在您的情况下,所有窗口都已创建并在主线程中运行。但是在工作线程中显示消息框并没有真正的减号(除了在消息框关闭之前工作线程处理将停止的事实)。