如何通过进程发送事件信号-C
我有一个由两个窗口组成的应用程序,一个窗口与另一个窗口通信,并向它发送一个包含两个整数的结构(在本例中是两个骰子) 我将在以下情况下使用事件:如何通过进程发送事件信号-C,c,winapi,events,multithreading,process,C,Winapi,Events,Multithreading,Process,我有一个由两个窗口组成的应用程序,一个窗口与另一个窗口通信,并向它发送一个包含两个整数的结构(在本例中是两个骰子) 我将在以下情况下使用事件: 进程a向进程b发送数据,进程b显示数据 流程a关闭,反过来关闭流程b 进程b关闭进程a,反过来关闭进程a 我注意到,如果第二个进程一直在等待第一个进程发送数据,那么程序将只是坐在那里等待,这就是在每个进程上实现线程的想法,我已经开始实现了 我遇到的问题是,我对线程和事件没有太多经验,因此我不确定实际实现我想要做的事情的最佳方法 我试图弄清楚另一个进程
- 进程a向进程b发送数据,进程b显示数据
- 流程a关闭,反过来关闭流程b
- 进程b关闭进程a,反过来关闭进程a
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);
}
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);
}
case WM_DESTROY:
{
SetEvent(hConsumerCloseEvent);
PostQuitMessage(0);
break;
}
我只能对事件使用Create/Set/Open方法,很抱歉之前没有提到
此外我在进程a中创建了一个新线程,让用户在监听关闭事件的同时与应用程序交互
创建线程:
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);
}
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);
}
case WM_DESTROY:
{
SetEvent(hConsumerCloseEvent);
PostQuitMessage(0);
break;
}
B关闭时A上的打开事件:
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;
}
}
}
在b中创建事件(在WM_CREATE中):
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);
}
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);
}
case WM_DESTROY:
{
SetEvent(hConsumerCloseEvent);
PostQuitMessage(0);
break;
}
将事件设置为B关闭时发出信号:
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);
}
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);
}
case WM_DESTROY:
{
SetEvent(hConsumerCloseEvent);
PostQuitMessage(0);
break;
}
正如您看到的,当事件发出信号时,应用程序A被设置为关闭。当我运行应用程序并关闭进程B时,进程A不会注意到已更改的信号,也不会关闭
编辑2:
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);
}
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);
}
case WM_DESTROY:
{
SetEvent(hConsumerCloseEvent);
PostQuitMessage(0);
break;
}
在使用GetLastError()之后;我能够识别OpenEvent的句柄为NULL,给出的错误为
错误\u未找到文件\u \u-2:系统错误
找不到指定的文件
如果我创建和读取事件的方法不正确,我已确保包含全局\前缀。听起来您可能想使用
。您可以使用信号量来表示可供进程b处理的数据项的数量。当数据项可用时,将其初始化为0计数,并用
递增。然后在进程b中调用
,或者调用它的一个bretheren,只有当信号量计数大于0时才会返回,此时计数会递减
这不是一个完整的解决方案,因为您仍然需要处理诸如共享缓冲区已满时要做什么之类的事情,但这应该会让您真正开始工作。信号量的好处在于,它们单独负责同步两个进程之间的队列深度。由于您仅限于使用事件对象,因此我建议使用进程间消息,而不是队列,或者如果您愿意的话,使用一个一个的队列 过程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);
}
过程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);
}
如果,正如我所猜测的,您实际上想要一个长度超过1的队列,那么您现在可以在进程b中实现排队逻辑。出于几个原因,您需要在单独的线程中执行此操作。队列逻辑的实现取决于您。根据您的效率需要,它可以是圆形数组或链表或
// 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);
}
}
不幸的是,我仅限于使用CreateEvent/SetEvent等。。方法集,很抱歉在问题中没有提及。我不明白为什么您提供的每个示例都有重复的事件集,以及每个进程如何判断另一个进程已更改状态?。出于某种原因,即使我将事件设置为false,程序仍然会立即看到它发出的信号,这是没有意义的。它实际上是由两个事件组成的一组。请注意,名称是相同的,运行的第一个进程将创建它们,第二个进程将获得预先存在的事件的句柄。我建议在这两种情况下都使用CreateEvent(与一个进程中的CreateEvent和另一个进程中的OpenEvent相比)的原因是,这意味着先启动哪个进程并不重要。事件被共享的事实就是你如何共享状态。我不知道为什么你会像往常一样看到这些事件。你能简单解释一下吗?MSDN文档只显示如何在一个过程中完成,而不是在两个过程之间完成,因此很难理解。您不理解的方面是什么?我添加了一些附加信息,以帮助解释我的错误所在。