如何通过进程发送事件信号 - C.

Jam*_*ing 6 c events winapi multithreading process

我有一个由两个窗口组成的应用程序,一个与另一个窗口通信,并向它发送一个构成两个整数的结构(在这种情况下是两个掷骰子).

我将在以下情况下使用事件:

  • 处理发送数据到进程b,进程b显示数据
  • 处理关闭,然后关闭流程b
  • 过程b关闭a,进而关闭过程a

我注意到如果第二个进程一直在等待第一个进程发送数据,那么程序将只是等待,这就是在每个进程上实现线程的想法,我已经开始实现它了.

我遇到的问题是我对线程和事件没有太多经验,所以我不确定实际实现我想做的最好的方法.

我正在尝试弄清楚其他进程如何知道被触发的事件,以便它可以完成它需要做的任务,我不明白一个独立于另一个进程的进程可以告诉事件的状态是什么特别是因为它需要在事件改变状态后立即采取行动.

谢谢你的帮助

编辑:

我只能使用创建/设置/打开方法来处理事件,抱歉之前没有提到它.

此外,我在进程A中创建了一个新线程,它允许用户在监听close事件时与应用程序进行交互.

创建线程:

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);
            }
Run Code Online (Sandbox Code Playgroud)

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;
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

在b中创建事件(在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);
            }
Run Code Online (Sandbox Code Playgroud)

将事件设置为在B关闭时发出信号:

case WM_DESTROY:
        {
            SetEvent(hConsumerCloseEvent);
            PostQuitMessage(0);
            break;
        }
Run Code Online (Sandbox Code Playgroud)

正如您可以看到事件发出信号时,应用程序A设置为关闭.当我同时运行应用程序并关闭进程B时,进程A不会注意到已更改的信号并且不会关闭.

编辑2:

使用GetLastError()后; 我能够确定OpenEvent的句柄是NULL,给出的错误是

ERROR_FILE_NOT_FOUND - 2:系统找不到指定的文件

我的创建事件和读取它的方法不正确,我确保包含Global \前缀.

tor*_*rak 5

信号量的好处是它们可以单独负责同步两个进程之间的队列深度。由于您仅限于使用事件对象,因此我建议使用进程间消息而不是队列,或者如果您愿意的话,可以使用一个队列。

工艺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);
}
Run Code Online (Sandbox Code Playgroud)

工艺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);
}
Run Code Online (Sandbox Code Playgroud)

如果,正如我猜测的,您实际上想要一个长度大于 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);
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 它实际上是一组两个事件。请注意,名称是相同的,第一个运行的进程将创建它们,第二个进程将获取预先存在的事件的句柄。我建议在这两种情况下使用 CreateEvent(与一个进程中的 CreateEvent 和另一个进程中的 OpenEvent 相比)的原因是,这应该意味着您首先启动哪个进程并不重要。共享事件的事实就是共享状态的方式。我不知道为什么你会像往常一样看到这些事件。 (2认同)