我使用Microsoft提供的以下代码作为模板:
#include <windows.h>
#include <stdio.h>
#define MAX_SEM_COUNT 10
#define THREADCOUNT 12
HANDLE ghSemaphore;
DWORD WINAPI ThreadProc( LPVOID );
int main( void )
{
HANDLE aThread[THREADCOUNT];
DWORD ThreadID;
int i;
// Create a semaphore with initial and max counts of MAX_SEM_COUNT
ghSemaphore = CreateSemaphore(
NULL, // default security attributes
MAX_SEM_COUNT, // initial count
MAX_SEM_COUNT, // maximum count
NULL); // unnamed semaphore
if (ghSemaphore == NULL)
{
printf("CreateSemaphore error: %d\n", GetLastError());
return 1;
}
// Create worker threads
for( i=0; i < THREADCOUNT; i++ )
{
aThread[i] = CreateThread(
NULL, // default security attributes
0, // default stack size
(LPTHREAD_START_ROUTINE) ThreadProc,
NULL, // no thread function arguments
0, // default creation flags
&ThreadID); // receive thread identifier
if( aThread[i] == NULL )
{
printf("CreateThread error: %d\n", GetLastError());
return 1;
}
}
// Wait for all threads to terminate
WaitForMultipleObjects(THREADCOUNT, aThread, TRUE, INFINITE);
// Close thread and semaphore handles
for( i=0; i < THREADCOUNT; i++ )
CloseHandle(aThread[i]);
CloseHandle(ghSemaphore);
return 0;
}
DWORD WINAPI ThreadProc( LPVOID lpParam )
{
// lpParam not used in this example
UNREFERENCED_PARAMETER(lpParam);
DWORD dwWaitResult;
BOOL bContinue=TRUE;
while(bContinue)
{
// Try to enter the semaphore gate.
dwWaitResult = WaitForSingleObject(
ghSemaphore, // handle to semaphore
0L); // zero-second time-out interval
switch (dwWaitResult)
{
// The semaphore object was signaled.
case WAIT_OBJECT_0:
// TODO: Perform task
printf("Thread %d: wait succeeded\n", GetCurrentThreadId());
bContinue=FALSE;
// Simulate thread spending time on task
Sleep(5);
// Release the semaphore when task is finished
if (!ReleaseSemaphore(
ghSemaphore, // handle to semaphore
1, // increase count by one
NULL) ) // not interested in previous count
{
printf("ReleaseSemaphore error: %d\n", GetLastError());
}
break;
// The semaphore was nonsignaled, so a time-out occurred.
case WAIT_TIMEOUT:
printf("Thread %d: wait timed out\n", GetCurrentThreadId());
break;
}
}
return TRUE;
}
我想对其进行调整,而不是由线程来确定信号量的填充方式,而是由进程完成,这意味着如果有正在运行的进程和/或它们的任何障碍物未关闭,信号量将被填充,实际上我通过使用此新功能更改线程功能的工作来完成此操作。
DWORD WINAPI ThreadProc( LPVOID lpParam )
{
// lpParam not used in this example
UNREFERENCED_PARAMETER(lpParam);
DWORD dwWaitResult;
BOOL bContinue=TRUE;
STARTUPINFO si;
PROCESS_INFORMATION pi;
memset(&si,0,sizeof(si));
si.cb=sizeof(si);
while(bContinue)
{
// Try to enter the semaphore gate.
dwWaitResult = WaitForSingleObject(
ghSemaphore, // handle to semaphore
0L); // zero-second time-out interval
CreateProcess("arbol.exe",NULL,NULL,NULL,0,0,NULL,NULL,&si,&pi);
WaitForSingleObject(pi.hProcess,INFINITE);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
switch (dwWaitResult)
{
// The semaphore object was signaled.
case WAIT_OBJECT_0:
// TODO: Perform task
printf("Thread %d: wait succeeded\n", GetCurrentThreadId());
bContinue=FALSE;
// Simulate thread spending time on task
Sleep(5);
// Release the semaphore when task is finished
if (!ReleaseSemaphore(
ghSemaphore, // handle to semaphore
1, // increase count by one
NULL) ) // not interested in previous count
{
printf("ReleaseSemaphore error: %d\n", GetLastError());
}
break;
// The semaphore was nonsignaled, so a time-out occurred.
case WAIT_TIMEOUT:
printf("Thread %d: wait timed out\n", GetCurrentThreadId());
break;
}
}
return TRUE;
}
这样一来,虽然决定信号量填充的是线程,但在实际意义上,它是由进程句柄的完全执行和关闭决定的。
但这似乎是解决此问题的la脚方式,我敢打赌,如果将来需要一些额外的操作,那么这样做可能会带来问题。
如何创建信号量,以便真正确定信号量的填充的是过程?要澄清的是,这将是一种我认为不可能的解决方案。
让我们考虑一下您可以通过以下方式创建流程:
aThread[i] = CreateProcess(
NULL, // default security attributes
0, // default stack size
(LPTHREAD_START_ROUTINE) ThreadProc,
NULL, // no thread function arguments
0, // default creation flags
&ThreadID); // receive thread identifier
则LPTHREAD_START_ROUTINE的工作原理是等效的,但对于过程而言。
信号量应该在Windows API中支持Interprocess Synchronization,但是我找不到任何专门使用进程的示例,而且我不知道该怎么做。
关于如何实现我想要的任何想法?
问候。
最佳答案
您想要一个命名信号量。每个进程通过使用相同的名称创建共享信号灯的地方。
创建一个命名信号量。和以前一样,但是最后一个参数将传递一个字符串:
HANDLE hSemaphore = CreateSemaphore(NULL,
MAX_SEM_COUNT,
MAX_SEM_COUNT,
L"TheSemaphoreForMyApp");
子进程在启动时可以附加到同一信号量,并可以使用OpenSemaphore对其进行处理。
HANDLE hSemaphore = OpenSemaphore(EVENT_ALL_ACCESS,
FALSE,
L"TheSemaphoreForMyApp");
您不必将字符串硬编码为信号灯名称。父进程可以每次创建一个唯一的名称,然后将该名称(例如命令行参数)传递给子进程。这将允许您的程序的多个实例与子进程进行协作。