Как определить был ли вызван SetEvent?
Мне необходимо сделать общение 2х разных программ через Pipe, клиент которой является инъекционной библиотекой для другого процесса. Далее, мне нужно сделать так, что бы поток был остановлен и клиент отключился, при завершении процесса, или же при поступлении сообщения о завершении работы сервера, или просто пропала связь с сервером.
Для синхронизации использую CreateEvent, OpenEvent и SetEvent.
И не могу понять, как используя WaitForSingleObject в цикле крутить обработку сообщений от сервера, и при этом не ждать вечно установки события через SetEvent.
/* Чего здесь ждать? */
while (?? != WaitForSingleObject(h_event, 0)) {
...
}
#include <Windows.h>
#include "kokin_client.h"
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
#define KOKIN_EVENT_NAME TEXT("kokin_process_detach")
#define KOKIN_PIPE_SERVER_NAME "kokin://shinra/renderer"
static HANDLE h_thread_handle = INVALID_HANDLE_VALUE;
static HANDLE h_thread_process_ended = INVALID_HANDLE_VALUE;
static struct kokin_client *p_client = KOKIN_CLIENT_INVALID;
DWORD CALLBACK kokin_start(LPVOID p_user_data) {
int i_result;
HANDLE h_event;
p_client = kokin_client_new();
if (KOKIN_CLIENT_INVALID == p_client) {
return 1;
}
i_result = kokin_client_connect(p_client, KOKIN_PIPE_SERVER_NAME);
if (0 != i_result) {
return 2;
}
h_event = OpenEvent(SYNCHRONIZE, TRUE, KOKIN_EVENT_NAME);
if (NULL == h_event) {
return 3;
}
/* Чего здесь ждать? */
while(?? != WaitForSingleObject(h_event, 0)) {
kokin_client_process(p_client);
}
}
/* https://docs.microsoft.com/ja-jp/windows/win32/dlls/dllmain */
BOOL WINAPI DllMain(
HINSTANCE hinstDLL, /* handle to DLL module */
DWORD fdwReason, /* reason for calling function */
LPVOID lpReserved) /* reserved */
{
/* Perform actions based on the reason for calling. */
switch (fdwReason)
{
case DLL_PROCESS_ATTACH: {
/* Initialize once for each new process. */
/* Return FALSE to fail DLL load. */
/* Double injection? Just fail to load and exit... */
if (INVALID_HANDLE_VALUE != h_thread_handle) {
return FALSE;
}
h_thread_process_ended = CreateEvent(NULL, TRUE, FALSE, KOKIN_EVENT_NAME);
h_thread_handle = CreateThread(NULL, 0, kokin_start, NULL, NULL, NULL);
} break;
case DLL_THREAD_ATTACH:
/* Do thread-specific initialization. */
break;
case DLL_THREAD_DETACH:
/* Do thread-specific cleanup. */
break;
case DLL_PROCESS_DETACH: {
/* Perform any necessary cleanup. */
(void) SetEvent(h_thread_process_ended);
(void) WaitForSingleObject(h_thread_handle, INFINITE);
(void) CloseHandle(h_thread_handle);
(void) CloseHandle(h_thread_process_ended);
kokin_client_destroy(&p_client);
} break;
}
return TRUE; /* Successful DLL_PROCESS_ATTACH. */
}
#ifdef __cplusplus
}
#endif // __cplusplus
P.S. Пожалуйста не предлагайте c++'ные потоки или что-то еще, только WinAPI.
Ответы (1 шт):
Если написать так:
while (WAIT_OBJECT_0 != WaitForSingleObject(h_event, 0)) {
kokin_client_process(p_client);
}
то цикл будет работать пока не будет вызван SetEvent
Так:
DWORD dwMilliseconds = 1000;
if (WAIT_OBJECT_0 == WaitForSingleObject(h_event, dwMilliseconds ))
{
kokin_client_process(p_client);
}
программа будет ожидать вызова SetEvent в течении dwMilliseconds
Если таймаут не устраивает, то можно использовать WaitForMultipleObjects
HANDLE lpHandles[2];
lpHandles[0] = h_event;
lpHandles[1] = stop_event;
DWORD dwMilliseconds = INFINITE;
while(true)
{
DWORD result = WaitForMultipleObjects(2, lpHandles, FALSE, dwMilliseconds );
switch(result)
{
case WAIT_OBJECT_0:
{
kokin_client_process(p_client);
break;
}
case WAIT_OBJECT_0 + 1:
{
break;
}
default:
continue;
}
}