C++系统命令行调用-挂GUI
C++ System Command Line Call - Hanging GUI
这 post/question 几乎模仿了我的问题的症状:
(Program unresponsive until function is done). 即使在遵循 post 的建议之后,症状仍然存在于这个特定的应用程序中,所以这里是详细信息。
它是一个 MS Visual C++ CLR 应用程序。它有一个 GUI,允许用户更改一些值,然后,在用户单击按钮时,1.) 首先对一个程序进行系统命令行调用,该程序对照明镇流器进行部分编程(这大约需要 25秒完成,命令行程序是唯一的选择)。 2.) 其次,使用另一供应商提供的 C++ 代码库将 16 "scene" 和 "dimming curve" 值与用户在 GUI 中设置的项目编程到照明镇流器。场景和调光曲线编程总共需要大约 5 秒才能完成。
根据链接项,当命令行应用程序运行时,此应用程序的 GUI 挂起。 "scene" 和 "dimming curve" 步骤的状态更新不会显示在 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在线程调用这个命令提示程序的过程中挂起,这样当剩下的场景和调光曲线编程发生时,客户端可以看到状态更新,因为它发生了,而不仅仅是看到最后出现的 "PASSED" 或 "FAILED" 消息。
不确定它是否相关,但是当 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 在等待时使用量激增。我错过了什么?
好吧,经过数周令人沮丧的各种线程和消息泵解决方案尝试的实验之后。在我的研究中,我读到如果线程正在创建 windows,我应该使用 MsgWaitForMultipleObjects 或 MsgWaitForMultipleObjectsEx。好吧,我的 system() 调用正在打开一个新的 window(尽管是一个命令 window),所以我一直在研究它。我终于回到了基础(这对我来说不是基础,因为我以前从未做过线程)并使用 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);
}
这 post/question 几乎模仿了我的问题的症状: (Program unresponsive until function is done). 即使在遵循 post 的建议之后,症状仍然存在于这个特定的应用程序中,所以这里是详细信息。
它是一个 MS Visual C++ CLR 应用程序。它有一个 GUI,允许用户更改一些值,然后,在用户单击按钮时,1.) 首先对一个程序进行系统命令行调用,该程序对照明镇流器进行部分编程(这大约需要 25秒完成,命令行程序是唯一的选择)。 2.) 其次,使用另一供应商提供的 C++ 代码库将 16 "scene" 和 "dimming curve" 值与用户在 GUI 中设置的项目编程到照明镇流器。场景和调光曲线编程总共需要大约 5 秒才能完成。
根据链接项,当命令行应用程序运行时,此应用程序的 GUI 挂起。 "scene" 和 "dimming curve" 步骤的状态更新不会显示在 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在线程调用这个命令提示程序的过程中挂起,这样当剩下的场景和调光曲线编程发生时,客户端可以看到状态更新,因为它发生了,而不仅仅是看到最后出现的 "PASSED" 或 "FAILED" 消息。
不确定它是否相关,但是当 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 在等待时使用量激增。我错过了什么?
好吧,经过数周令人沮丧的各种线程和消息泵解决方案尝试的实验之后。在我的研究中,我读到如果线程正在创建 windows,我应该使用 MsgWaitForMultipleObjects 或 MsgWaitForMultipleObjectsEx。好吧,我的 system() 调用正在打开一个新的 window(尽管是一个命令 window),所以我一直在研究它。我终于回到了基础(这对我来说不是基础,因为我以前从未做过线程)并使用 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);
}