【发布时间】:2015-06-29 02:33:28
【问题描述】:
这个帖子/问题几乎模仿了我的问题的症状: (Program unresponsive until function is done). 即使遵循了该帖子的建议,症状仍然存在于这个特定的应用程序中,所以这里是详细信息。
它是一个 MS Visual C++ CLR 应用程序。它有一个 GUI,允许用户更改一些值,然后,在用户单击按钮时,1.) 首先对部分编程照明镇流器的程序进行系统命令行调用(这大约需要 25 秒才能完成,并且命令行程序是唯一的选择)。 2.)其次,使用其他供应商提供的C++代码库将16个“场景”和“调光曲线”值与用户在GUI中设置的项目一起编程到照明镇流器。场景和调光曲线编程总共需要大约 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 不挂起,以便在发生剩余场景和调光曲线编程时,客户端可以看到状态更新,而不仅仅是看到最后出现的“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 使用率飙升的任何想法等待。我错过了什么?
【问题讨论】:
-
您的 do/while 循环会像在主线程中运行命令一样有效地挂起 UI。
-
@RetiredNinja:谢谢。我曾思考过这一点。 GUI 确实会挂起并延长睡眠时间。我曾尝试在 do/while 循环中对 GUI 进行更新以帮助避免这种情况,但最终还是挂起。根据要求(可能还有我正在编程的设备的技术限制),我不能让命令行应用程序与场景和调光曲线编程并行运行。关于如何保持主线程等待(或至少模拟它正在等待)直到命令行程序线程完成的任何建议?
-
@RetiredNinja:更新:循环已更新为
WaitForSingleObject(hThread, INFINITE);,但仍然出现挂起。 -
您在主线程中所做的任何阻塞操作,无论是系统命令、循环中的睡眠还是永远等待都会冻结您的 UI。您需要考虑更多事件驱动或回调类型的解决方案。您可以在另一个线程中运行长时间运行的命令,然后在完成时通知主线程。
-
@RetiredNinja:长命令现在运行一个线程。我面临着如何让主线程等待该通知而不做任何会阻塞/导致挂起或对 CPU 征税的挑战(没有睡眠命令的循环)。没有开发。在接下来的 2 天内我可以使用 PC,我看不到我之前的尝试或尝试任何新的东西。但我会搜索非阻塞线程示例,看看我能找到什么。您能否指出(或者您有)主线程在等待衍生线程完成时的任何示例或算法吗?
标签: c++ multithreading system