gpt4 book ai didi

c++ - 为什么win32线程不自动退出?

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:41:41 24 4
gpt4 key购买 nike

背景:

在我用 C++ 编写的应用程序中,我创建了一个工作线程,该工作线程又使用 CreateThread() 创建了两个线程.工作线程创建的两个线程通过使用 Windows Web Services API 实现的客户端与 WCF 服务通信。它提供 C/C++ 应用程序编程接口(interface) (API),用于构建基于 SOAP 的 Web 服务和客户端。我的应用程序使用此 API 的客户端。

问题:

我面临的问题是,除工作线程外,所有其他线程都正常退出,正如您自己所见,在下图中 WorkerThreadProc 不使用 CPU 周期但它不导出。还有一些其他线程正在运行,它们不是由我创建的,而是由运行时创建的。

线程状态如下(由 ProcessExplorer 报告):

  • WorkerThreadProc 处于Wait:WrUserRequest 状态。
  • wWinMainCRTStartup 处于Wait:UserRequest 状态。
  • 所有TpCallbackIndependent 都处于Wait:WrQueue 状态。

他们还在等什么?我需要调查哪些可能的原因?另外,WrUserRequestUserRequest 有什么区别? WrQueue 是什么意思?我完全不知道这里发生了什么。

enter image description here


这是我的 WorkerThreadProc 代码。除了函数底部的最后一个日志语句外,我已经删除了所有日志语句:

DWORD WINAPI WorkerThreadProc(PVOID pVoid)
{

//Initialize GDI+
GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;

Status status = GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
if ( status != Status::Ok )
{
return 1;
}

GuiThreadData *pGuiData = (GuiThreadData*)pVoid;

auto patternIdRequestQueue= new PatternIdRequestQueue();
auto resultQueue = new ResultQueue();

auto patternManager = new PatternManager(patternIdRequestQueue);
LocalScheduler *pScheduler = new LocalScheduler(resultQueue, patternManager);

bool bInitializationDone = pScheduler->Initialize(pGuiData->m_lpCmdLine);
if ( !bInitializationDone )
{
return 0;
}

//PatternIdThread
PatternIdThread patternIdThread(patternIdRequestQueue);
DWORD dwPatternIdThreadId;
HANDLE hPatternIdThread = CreateThread(NULL, 0, PatternIdThreadProc, &patternIdThread, 0, &dwPatternIdThreadId);

ResultPersistence resultPersistence(resultQueue);
DWORD dwResultPersistenceThreadId;
HANDLE hResultPersistenceThread = CreateThread(NULL, 0, ResultPersistenceThreadProc, &resultPersistence, 0, &dwResultPersistenceThreadId);

pScheduler->ScheduleWork(pGuiData->m_hWnd, pGuiData->m_hInstance, ss.str());

pScheduler->WaitTillDone();
patternIdThread.Close();
resultPersistence.Close();

delete pScheduler;

//Uninitialize GDI+
GdiplusShutdown(gdiplusToken);

dwRet = WaitForSingleObject(hPatternIdThread, INFINITE);
CloseHandle(hPatternIdThread);

dwRet = WaitForSingleObject(hResultPersistenceThread,INFINITE);
CloseHandle(hResultPersistenceThread);

SendMessage(pGuiData->m_hWnd, WM_CLOSE, 0, 0);

//IMPORTANT : this verbose message is getting logged!
T_VERBOSE(EvtSrcInsightAnalysis, 0, 0, "After sending message to destroy window");

delete patternManager;
delete patternIdRequestQueue;
delete resultQueue;
return 0;
}

请参阅T_VERBOSE 宏,它用于记录详细消息。我看到消息正在记录,但线程没有退出!


编辑:

我刚刚在我的 WorkerThreadProc 中注释了以下行,然后工作线程正常退出!

SendMessage(pGuiData->m_hWnd, WM_CLOSE, 0, 0);

这是否意味着 SendMessage 是罪魁祸首?为什么它会阻塞调用线程的线程?

最佳答案

如果我们查看SendMessage 的文档,您会看到这个小引用:

To send a message and return immediately, use the SendMessageCallback or SendNotifyMessage function. To post a message to a thread's message queue and return immediately, use the PostMessage or PostThreadMessage function.

还有这个:

Messages sent between threads are processed only when the receiving thread executes message retrieval code. The sending thread is blocked until the receiving thread processes the message. However, the sending thread will process incoming nonqueued messages while waiting for its message to be processed. To prevent this, use SendMessageTimeout with SMTO_BLOCK set. For more information on nonqueued messages, see Nonqueued Messages.

因此我们可以看到 SendMessage 将阻塞直到消息被处理,这可能会以某种方式导致您的代码出现死锁,因为 msgproc 不驻留在您的工作线程中,从而导致上下文切换(仅在线程的队列为消息抽取时触发)。尝试使用 PostMessage,它会立即返回。

编辑:还有一个不错的小信息 here来自 SendMessage

的消息死锁

关于c++ - 为什么win32线程不自动退出?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9227117/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com