Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/147.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为什么win32线程没有';你不能自动退出吗?_C++_Multithreading_Wcf_Web Services - Fatal编程技术网

C++ 为什么win32线程没有';你不能自动退出吗?

C++ 为什么win32线程没有';你不能自动退出吗?,c++,multithreading,wcf,web-services,C++,Multithreading,Wcf,Web Services,背景: 在C++编写的应用程序中,我创建了一个辅助线程,它使用两个线程创建两个线程。worker thread创建的两个线程通过一个客户端与WCF服务对话,该客户端使用提供C/C++应用程序编程接口(API)的客户端实现,用于构建基于SOAP的web服务和客户端。我的应用程序仅使用此API实现客户端 问题: 我面临的问题是,除了工作线程之外,所有其他线程都会正常退出,正如您可以看到的,在下图中,WorkerThreadProc没有使用CPU周期,但它不会退出。还有一些运行的线程不是由我创建的,而

背景:

在C++编写的应用程序中,我创建了一个辅助线程,它使用两个线程创建两个线程。worker thread创建的两个线程通过一个客户端与WCF服务对话,该客户端使用提供C/C++应用程序编程接口(API)的客户端实现,用于构建基于SOAP的web服务和客户端。我的应用程序仅使用此API实现客户端

问题:

我面临的问题是,除了工作线程之外,所有其他线程都会正常退出,正如您可以看到的,在下图中,
WorkerThreadProc
没有使用CPU周期,但它不会退出。还有一些运行的线程不是由我创建的,而是由运行时创建的

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

  • WorkerThreadProc
    处于等待:WrUserRequest状态
  • wWinMainCRTStartup
    处于Wait:UserRequest状态
  • 所有
    TpCallbackIndependent
    都处于Wait:WrQueue状态
他们在等什么?我需要调查哪些可能的原因?另外,WrUserRequest和UserRequest之间有什么区别?“排队”是什么意思?我完全不知道这里发生了什么


这是我的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\u VERBOSE
宏,它用于记录详细消息。我看到消息正在被记录,但是线程没有退出


编辑:

我刚刚在我的
WorkerThreadProc
中注释了下面的一行,然后工作线程优雅地退出了

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

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

如果我们查看
SendMessage
的文档,您可以看到以下小引号:

要发送消息并立即返回,请使用SendMessageCallback 或SendNotifyMessage函数。将消息发布到线程的消息 排队并立即返回,请使用PostMessage或PostThreadMessage 功能

这是:

线程之间发送的消息仅在接收 线程执行消息检索代码。发送线程被阻止 直到接收线程处理消息为止。然而,发送 线程将在等待消息到达时处理传入的非排队消息 要处理的消息。要防止出现这种情况,请将SendMessageTimeout与 SMTO_块集。有关非排队消息的详细信息,请参阅 非排队消息

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


编辑:还有一个关于消息死锁的小信息,它来自
SendMessage

在线程句柄退出后是否调用CloseHandle()?您应该使用WaitForSingleObject()等待线程完成。@事实:当然,是的!是的,我正在使用
WaitForSingleObject
等待线程完成!你为什么不使用像
boost::thread
这样的抽象,这些抽象被证明可以很好地工作(甚至是可移植的)?@plasmah:我不需要可移植性。另外,你的意思是win32线程是坏的(并且被证明是坏的)?
boost::thread
在内部使用什么?@plasmah:如果我提出了一些关于
boost::thread
的问题,该怎么办?我发现你的论点很弱。在我自己发现了
SendMessage()
的问题后(正如我在我的问题中发布的那样),我在MSDN上阅读了文档(您已发布为答案),但我没有得到的是
SendMessage
没有返回的原因。它不返回意味着receiving线程不处理消息,这反过来意味着如果我使用
PostMessage
,那么即使在那时它也不会处理消息。虽然,它将解决阻塞线程的问题,但真正的问题(我们现在知道)仍然存在,这就是:消息没有被处理@纳瓦兹:这一部分最好使用Spy++之类的工具来解决,我还遇到了一个类似的问题,
WM_CLOSE
消息没有被处理,将其追溯到另一个返回错误值的窗口消息,导致
WM_CLOSE
消息从队列中删除,因此无法处理