Windows MFC工作线程无法退出

时间:2016-11-05 09:16:38

标签: windows multithreading mfc

我想在MFC编辑控件中显示命令行程序的标准输出。所以我通过AfxBeginThread启动一个工作线程来通过PostMessage更新UI(这部分工作得很好),工作线程通过管道与命令行子进程通信。但是我的工作线程无法读取管道中的任何内容(ReadFile总是返回FALSE),即使子进程退出,我的工作也无法退出。所以请帮助我。

这是我的代码。

创建子进程部分:

BOOL CMFCApplication3Dlg::execCmd(LPCSTR pCmdArg)
{
    //ASSERT(s_hCmdProcess == NULL);
    if (s_hCmdProcess != NULL)
    {
        return FALSE;
    }
    STARTUPINFO si; // specifies startup parameters for child process.
    ZeroMemory(&si, sizeof(STARTUPINFO));

    si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES; // STARTF_USESTDHANDLES is Required.
    si.hStdOutput = s_cmdout_ChildSide; // Requires STARTF_USESTDHANDLES in dwFlags.
    si.hStdError = s_cmdout_ChildSide; // Requires STARTF_USESTDHANDLES in dwFlags.
                                   // si.hStdInput remains null.
    si.wShowWindow = SW_HIDE; // Prevents cmd window from flashing. Requires STARTF_USESHOWWINDOW in dwFlags.

    PROCESS_INFORMATION pi;
    ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));

    // Create the child process.
    BOOL result = CreateProcess(
        NULL,
        (LPSTR)pCmdArg,     // command line
        NULL,               // process security attributes
        NULL,               // primary thread security attributes
        TRUE,               // TRUE=handles are inherited. Required.
        CREATE_NEW_CONSOLE, // creation flags
        NULL,               // use parent's environment
        NULL,               // use parent's current directory
        &si,                // __in, STARTUPINFO pointer
        &pi);               // __out, receives PROCESS_INFORMATION

    if (result)
    {
        s_hCmdProcess = pi.hProcess;
        s_hCmdProcessThread = pi.hThread;
    }

    return result;
}

创建管道部分:

LRESULT CMFCApplication3Dlg::createPipe()
{
    ASSERT(s_cmdout_ChildSide == NULL && s_cmdout_MainSide == NULL);
    if (s_cmdout_ChildSide != NULL || s_cmdout_MainSide != NULL) return FALSE;
    SECURITY_ATTRIBUTES saAttr = { sizeof(SECURITY_ATTRIBUTES) };
    saAttr.bInheritHandle = TRUE; 
    saAttr.lpSecurityDescriptor = NULL;
    return CreatePipe(&s_cmdout_MainSide, &s_cmdout_ChildSide, &saAttr, 0);
}

工作线程部分:

void CMFCApplication3Dlg::startWorkThread()
{
    if (s_hThread == NULL) 
    {
        if (s_hThreadEvent != NULL) CloseHandle(s_hThreadEvent);
        s_hThreadEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
        //s_hThread = AfxBeginThread(TestThreadProc, this);
        s_hThread = AfxBeginThread(ReadCmdOutProc, this);
    }
}

UINT ReadCmdOutProc(LPVOID pParam)
{
    CWnd *hDlg = (CWnd *)pParam;

    //start the child process
    BOOL result = CMFCApplication3Dlg::execCmd("ping 127.0.0.1 -n 99");
    ASSERT(CMFCApplication3Dlg::s_hCmdProcess != NULL);

    for(;;)
    {

        DWORD dwRetVal_cmd;
        //wait for child process quit.
        dwRetVal_cmd = WaitForSingleObject(CMFCApplication3Dlg::s_hCmdProcess,100);

        DWORD dwRead = 0;
        CHAR chBuf[4096];
        BOOL readResult = ReadFile(CMFCApplication3Dlg::s_cmdout_MainSide, chBuf, 4096, &dwRead, NULL);
        if (readResult) 
        {
            chBuf[dwRead] = 0;
            TRACE("read: %s\n",chBuf);
            CString* cmdread = new CString(chBuf, dwRead);
            //send ui thread update message.
            MsgWrapper::Post(hDlg, WM_APP + 11, (WPARAM)cmdread);
        }

        if (dwRetVal_cmd != WAIT_TIMEOUT)
        {
            TRACE("thread quit\n");
            //release the resource
            CMFCApplication3Dlg::releaseCmd();
            GetExitCodeThread(CMFCApplication3Dlg::s_hThread, &dwExitCode);
            AfxEndThread(dwExitCode);
            CMFCApplication3Dlg::s_hThread = NULL;
            break;
        }
    }
}

0 个答案:

没有答案