2010-04-22 16 views
6

Tengo una aplicación que consta de dos ventanas, una se comunica con la otra y le envía una estructura que contiene dos enteros (en este caso, dos rollos de un dado).Cómo enviar señal de evento a través de procesos - C

Me va a utilizar eventos para las siguientes circunstancias:

  • Proceso A envía datos para procesar b, proceso b muestra los datos
  • de proceso A se cierra, a su vez cierre proceso b
  • Proceso B se cierra a, a su vez proceso de cierre a

Me he dado cuenta de que si el segundo proceso está esperando constantemente que el primer proceso envíe datos, entonces el programa estará esperando, wh Aquí es donde se produjo la idea de implementar subprocesos en cada proceso y ya comencé a implementarlo.

El problema que tengo es que no tengo exactamente mucha experiencia con hilos y eventos, así que no estoy seguro de la mejor manera de implementar realmente lo que quiero hacer.

Estoy tratando de averiguar cómo el otro proceso sabrá del evento que se está disparando para que pueda hacer las tareas que necesita hacer, no entiendo cómo un proceso que está separado de otro puede decir lo que el indica que los eventos se encuentran en especial ya que debe actuar tan pronto como el evento haya cambiado de estado.

Gracias por cualquier ayuda

Editar:

sólo puedo utilizar el Crear/Set/métodos abiertos para eventos, lo siento por no mencionar que antes.

Además,, creo un nuevo hilo en el proceso A que permite al usuario interactuar con la aplicación mientras escucha el evento de cierre.

Crear hilo:

hCreateEventThread = CreateThread(
       NULL,  // lpThreadAttributes (default) 
       0,   // dwStackSize (default) 
       ThreadFunc, // lpStartAddress 
       NULL,  // lpParameter 
       0,   // dwCreationFlags 
       &hCreateEventThreadID // lpThreadId (returned by function) 
       ); 

      if(hCreateEventThread != NULL) 
      { 
       MessageBox(hMainWindow,L"Thread created!",L"Success!",MB_OK); 
      } 

evento de apertura el A cuando B se cierra: evento

DWORD WINAPI ThreadFunc(LPVOID passedHandle) 
    { 
     hConsumerCloseEvent = OpenEvent(EVENT_ALL_ACCESS, FALSE, TEXT("Global\\ConsumerCloseEvent")); 

     while(TRUE) 
     { 
      dwCloseResult = WaitForSingleObject(hConsumerCloseEvent,INFINITE); 

      switch (dwCloseResult) 
      { 
       // State of object is signalled 
      case WAIT_OBJECT_0: 
       //Consumer has closed, exit program. 
       //CloseHandle(hDiceRoll); 
       //CloseHandle(hCloseEvent); 
       //CloseHandle(hCreateEventThread); 
       ExitProcess(1); 
       break; 
      default: 
       return; 
      } 
     } 
    } 

Creación en ter (En WM_CREATE):

hConsumerCloseEvent = CreateEvent( 
       NULL,    // default security attributes 
       TRUE,    // manual-reset event 
       TRUE,    // initial state is nonsignaled 
       TEXT("Global\\ConsumerCloseEvent") // object name 
       ); 

      if(hConsumerCloseEvent == NULL) 
      { 
       MessageBox(hMainWindow,L"CreateEvent failed",L"Error",MB_OK); 
      } 

Ajuste del evento para señalizado cuando B se cierra:

case WM_DESTROY: 
     { 
      SetEvent(hConsumerCloseEvent); 
      PostQuitMessage(0); 
      break; 
     } 

Como se puede ver cuando se señaliza el evento, la aplicación A se establece para cerrar. Cuando ejecuto ambas aplicaciones y cierro el proceso B, el proceso A no detecta la señal modificada y no se cierra.

Editar 2:

Después de usar el GetLastError(); Yo era capaz de identificar que el mango a la OpenEvent era NULL, el error dado es

ERROR_FILE_NOT_FOUND - 2: El sistema no puede encontrar el archivo especificado

es mi método de crear el evento y leyéndolo incorrectamente, me he asegurado de incluir el prefijo Global \.

Respuesta

3

Lo bueno de los semáforos es que, por sí solos, se encargan de sincronizar la profundidad de cola entre los dos procesos. Como en su lugar está limitado a usar objetos de Evento, le sugiero que tenga los mensajes entre procesos en lugar de una cola, o una cola de uno si lo desea.

Proceso A

// In the initialization code 
... 
hMessageEmptiedEvent = CreateEvent(NULL, FALSE, TRUE, _T("MessageEmptied")); 
hMessageSentEvent = CreateEvent(NULL, FALSE, FALSE, _T("MessageSent")); 

// Call this function when you want to send the data to process b 
void sendData(struct diceData data) 
{ 
    // Make sure any pre-existing message has been processed 
    WaitForSingleObject(hMessageEmptiedEvent, INFINITE); 
    // Copy the data into the shared buffer 
    *(struct diceData *) pBuf = data; 
    // Signal the other process that data is ready 
    SetEvent(hMessageSentEvnt); 
} 

Proceso B

// In the initialization code 
... 
hMessageEmptiedEvent = CreateEvent(NULL, FALSE, TRUE, _T("MessageEmptied")); 
hMessageSentEvent = CreateEvent(NULL, FALSE, FALSE, _T("MessageSent")); 

// Call this function when you want to recieve data from process a 
struct diceData readData() 
{ 
    struct diceData data; 

    // Wait for a message to become available 
    WaitForSingleObject(hMessageSentEvent, INFINITE); 
    // Copy the data from the shared buffer 
    data = * (struct diceData *)pBuf; 
    // Signal the other process that message has been read. 
    SetEvent(hMessageEmptiedEvnt); 
} 

Si, como supongo, que realmente quiere tener una cola de más de una longitud ahora se puede implementar la lógica de gestión de colas en proceso b. Querrás hacer eso en un hilo separado por un par de razones. La implementación de la lógica de cola depende de usted. Dependiendo de sus necesidades de eficiencia, podría ser una matriz circular o una lista vinculada o ???

// In process b's initialzation add a thread to do the queueing 
initializeEmptyQueue(); 
hQueueingThread = CreateThread(NULL, 0, enqueueLoop, NULL, 0, NULL); 


DWORD enqueueLoop(LPVOID ignored) 
{ 
    while (TRUE) 
    { 
    struct diceData data; 
    data = getData(); 
    enqueueData(data); 
    } 
} 
+0

No entiendo por qué tiene conjuntos duplicados de eventos para cada muestra que proporcionó, también ¿cómo puede cada proceso decir que el otro ha cambiado de estado ?. Por alguna razón, aunque he configurado el evento en falso, el programa aún lo ve como indicado de inmediato, no tiene sentido. –

+0

Es en realidad un conjunto de dos eventos. Tenga en cuenta que los nombres son los mismos, el primer proceso que se ejecutará los creará, el segundo obtendrá un control de los eventos preexistentes. El motivo por el que sugerí el uso de CreateEvent en ambos casos (en comparación con CreateEvent en un proceso y OpenEvent en el otro) es que debería significar que no importa qué proceso se inicie primero. El hecho de que los eventos se compartan es la forma en que comparte el estado. No sé por qué estarías viendo los eventos como siempre se señaló. – torak

+0

¿Podría explicarlo más simple? La documentación de MSDN solo tiende a mostrar cómo hacerlo en un proceso, no entre dos, por lo que es difícil de entender. –

2

Parece que es posible que desee utilizar CreateSemaphore. Puede usar un semáforo para representar la cantidad de elementos de datos disponibles para el proceso b. Inicialízalo hasta contar 0, cuando un elemento de datos esté disponible increméntalo con ReleaseSemaphore. Luego, en su proceso b, llame al WaitForSingleObject, o uno de sus bretheren, que solo volverá cuando el recuento de semáforos esté por encima de 0, momento en el que se reduce el recuento.

Esto no es una solución completa porque todavía tiene que manejar cosas como qué hacer cuando su búfer compartido está lleno, pero debe hacerlo comenzar bien.

+0

Desafortunadamente, estoy restringido a usar solo el conjunto de métodos CreateEvent/SetEvent, etc., lo siento por no mencionarlo en la pregunta. –

Cuestiones relacionadas