2012-02-10 13 views
6

Antecedentes:¿Por qué el subproceso win32 no sale automáticamente?

En mi aplicación escrita en C++, que crea un subproceso de trabajo que a su vez crea dos hilos utilizando CreateThread(). Los dos subprocesos que crea el hilo de trabajo, hable con WCF Service a través de un cliente que se implementa utilizando Windows Web Services API que ofrece la interfaz de programación de aplicaciones C/C++ (API) para crear clientes y servicios web basados ​​en SOAP. Mi aplicación implementa solo el cliente que usa esta API.

Problema:

El problema que estoy enfrentando es que todos los otros hilos salen con gracia, salvo el subproceso de trabajo, como se puede ver a ti mismo, en la siguiente imagen que utiliza WorkerThreadProc no hay ciclos de CPU, sin embargo, doesn no salir También hay algunos otros subprocesos en ejecución que no son creados por mí, sino por el tiempo de ejecución.

estados

el hilo son los siguientes (según lo informado por ProcessExplorer):

  • WorkerThreadProc es en Wait: WrUserRequest estado.
  • wWinMainCRTStartup está en Espera: UserRequest estado.
  • Todos TpCallbackIndependent están en Esperar: estado de WrQueue.

¿Qué están esperando? ¿Cuáles podrían ser las causas posibles que necesito investigar? Además, ¿cuál es la diferencia entre WrUserRequest y UserRequest? ¿Y qué significa WrQueue? No tengo idea de qué está pasando aquí.

enter image description here


Aquí está mi código WorkerThreadProc. He quitado todas las declaraciones de registro, excepto la última en la parte inferior de la función:

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; 
} 

Por favor ver la T_VERBOSE macro, que se utiliza para iniciar la sesión de mensaje detallada. Veo que el mensaje se está registrando, ¡pero el hilo no se cierra!


EDIT:

simplemente les comentaba la siguiente línea en mi WorkerThreadProc, entonces subproceso de trabajo termina sin novedad!

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

¿Quiere decir que SendMessage es el culpable? ¿Por qué bloquearía el hilo el hilo de llamada?

+0

¿Estás llamando CloseHandle() en el controlador de subproceso después de que salga? Debería usar WaitForSingleObject() para esperar a que finalice el subproceso. –

+0

@infact: ¡Por supuesto, sí! Y sí, estoy usando 'WaitForSingleObject' para esperar a que termine el hilo. – Nawaz

+0

¿Por qué no usas abstracciones como 'boost :: thread' que funcionan bien (y son incluso portátiles)? – PlasmaHH

Respuesta

3

Si nos fijamos en la documentación para SendMessage, se puede ver esta pequeña cita:

Para enviar un mensaje y volver de inmediato, utilice la función SendMessageCallback o SendNotifyMessage. Para publicar un mensaje en el mensaje de un hilo queue y devolver inmediatamente, utilice la función PostMessage o PostThreadMessage .

y esto:

Los mensajes enviados entre los hilos se procesan sólo cuando la recepción de hilo ejecuta el código de recuperación de mensajes. El hilo de envío está bloqueado hasta que el hilo receptor procese el mensaje. Sin embargo, el hilo que envía procesará los mensajes entrantes no en cola mientras espera que se procese su mensaje . Para evitar esto, use SendMessageTimeout con conjunto SMTO_BLOCK. Para obtener más información sobre mensajes no en cola, consulte Mensajes no en cola.

por lo que desde este podemos ver SendMessage bloqueará hasta que el mensaje es procesado, que de alguna manera puede conducir a un punto muerto en su código, como el msgproc no reside en el subproceso de trabajo, lo que lleva a un cambio de contexto (que solo se activa cuando se bombea la cola del hilo para los mensajes). Intente usar PostMessage, que devuelve inmediatamente.

EDIT: también hay un poco de buen pedazo de información here en callejones sin salida de mensajes de SendMessage

+0

Después de descubrir el problema con 'SendMessage()' (como publiqué esto en mi pregunta), leí el documento (que ha publicado como respuesta) en MSDN, pero lo que no obtengo es por qué ' SendMessage' no regresa. No devuelve significa que el hilo de recepción no procesa los mensajes, lo que a su vez implica que si uso 'PostMessage', entonces no procesará los mensajes incluso entonces. Aunque, resolverá el problema de bloquear el hilo, pero el problema real (que * ahora * sabemos) todavía está allí, que es este: ¡los mensajes no se están procesando! – Nawaz

+0

@Nawaz: Esa parte se resolvería mejor usando algo como Spy ++, también me enfrenté a un problema similar con los mensajes 'WM_CLOSE' que no se procesaban, lo remonté a otro mensaje de ventana devolviendo el valor incorrecto, dando como resultado el mensaje' WM_CLOSE' eliminado de la cola para que no pueda procesarse – Necrolis

Cuestiones relacionadas