C ++系统命令行调用 - 挂起GUI

时间:2015-06-29 02:33:28

标签: c++ multithreading system

这篇文章/问题几乎模仿了我的问题的症状: Program unresponsive until function is done)。即使遵循该帖子的建议,症状仍然存在于此特定应用中,因此以下是详细信息。

它是一个MS Visual C ++ CLR应用程序。它有一个GUI,允许用户更改一些值,然后,在用户点击按钮时,1。)首先对部分编程照明镇流器的程序进行系统命令行调用(这需要大约25秒完成,命令行程序是唯一的选择)。 2.)第二,节目16"场景"和"调光曲线"使用由GUI中的用户使用由另一个供应商提供的C ++代码库的照明镇流器设置的项目的值。场景和调光曲线编程总共需要约5秒钟才能完成。

根据链接项,当命令行应用程序运行时,此应用程序的GUI将挂起。来自"场景的状态更新"和"调光曲线"步骤不会显示在GUI中。根据我所读到的建议,命令行调用是通过线程调用完成的。

以下是代码的简化版本:

    void main() {
        DWORD ThreadID;
        HANDLE hThread = CreateThread(0, 0, wfThread, &args, 0, &ThreadID);
        DWORD lpExitCode;
        string strMsg = "";
        do {
            Sleep(1000);
            GetExitCodeThread(hThread, &lpExitCode);
        } while (STILL_ACTIVE == lpExitCode);
        CloseHandle(hThread);
    }

    DWORD WINAPI wfThread(LPVOID lpParam) {
        std::stringstream ssCmd;
        ssCmd << "C:\\PROGRA~2\\PHILIP~1\\MULTIO~1.exe /f \"C:\\Users\\User\\Desktop\\Data\\driver 929000702302 490ma 60w soco 02001 code.xml\" /w \"C:\\Users\\User\\Desktop\\Data\\WorkflowConfig.txt\"  /v info /c halt";
        system(ssCmd.str().c_str());
        return 0;
    }

目标是在线程调用此命令提示程序期间挂起GUI,以便在剩余场景和调光曲线编程发生时,客户端可以在发生状态时查看状态更新,而不仅仅是看到最终&#34; PASSED&#34;或者&#34; FAILED&#34;最后发生的消息。

不确定它是否相关,但程序在GUI挂起时确实按预期运行。照明镇流器按预期编程,日志文件按预期写入。在命令行调用期间以及几秒钟后停止挂起GUI几乎没有成功。

更新:

我更新了代码,因此调用了线程。我仍然无法让主线程(UI)等待/接受任何用户输入而没有循环,这仍然在运行CPU - 最重要的是,仍然挂起,即使MsgWaitForMultipleObjectsEx是应该阻止这种情况,并且我在等待线程完成时更新UI。

        workFlowArgs args = { msclr::interop::marshal_as<std::string>(txtWorkflowProgram->Text), msclr::interop::marshal_as<std::string>(txtXmlFolder->Text), msclr::interop::marshal_as<std::string>(cboXmlSelect->Text), "WorkflowConfig.txt" };
        DWORD ThreadID;
        HANDLE hThread = CreateThread(0, 0, wfThread, &args, 0, &ThreadID);
        HANDLE hThreads[] = { hThread };
        DWORD lpExitCode;
        string strMsg = "";

        do {
            DWORD res = MsgWaitForMultipleObjectsEx(_countof(hThreads), hThreads, 0, QS_ALLEVENTS, 0);
            if (strMsg == "..........")
                strMsg = "";
            else
                strMsg = strMsg + ".";
            txtStatus->Text = msclr::interop::marshal_as<System::String^>(strMsg);
            txtStatus->Refresh();

            switch (res)
            {
            case WAIT_OBJECT_0 + 0:
                OutputDebugStringW(L"Completed!!");
            case WAIT_OBJECT_0 + _countof(hThreads):
                OutputDebugStringW(L"Still Going\n");
                txtStatus->Text = msclr::interop::marshal_as<System::String^>(strMsg);
                txtStatus->Refresh();
            case WAIT_IO_COMPLETION:
                break;
            }
            GetExitCodeThread(hThread, &lpExitCode);
        }  while (STILL_ACTIVE == lpExitCode);

UI似乎需要比以前更长的时间(有时它实际上不会挂起),但我仍在积极寻找任何阻止UI挂起的想法并保持CPU使用率不会出现高峰#39;等待。我错过了什么?

1 个答案:

答案 0 :(得分:0)

好吧,经过几周令人沮丧的实验,尝试各种线程和消息泵解决方案。在我的研究中,我读过如果线程正在破坏窗口,我应该使用MsgWaitForMultipleObjects或MsgWaitForMultipleObjectsEx。好吧,我的system()调用IS打开一个新窗口(尽管是一个命令窗口),所以我一直在探索它。我终于回到基础(这对我来说不是基本的,因为我以前从未做过线程化)并使用了GetMessage并在等待线程完成时创建了典型的消息泵。

HANDLE hThread = CreateThread(0, 0, wfThread, &args, 0, &ThreadID);
MSG msg = { 0 };
GetExitCodeThread(hThread, &lpExitCode);
BOOL bRet;
while (((bRet = GetMessage(&msg, NULL, 0, 0)) != 0) && (STILL_ACTIVE == lpExitCode)) {
    if (bRet == -1)
        // Handle Error
        MessageBox::Show("GetMessage Error");
    else {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    GetExitCodeThread(hThread, &lpExitCode);
}