我的服务器上有两个线程,一个工作线程和一个接收线程。有一个共享队列,其中包含此服务器的所有活动客户端的列表,即队列具有每个活动客户端的 IP 和端口号
工作线程处于临界区,不断从队列中弹出数据,并向弹出的每个 IP 和端口号发送消息。
接收线程只等待新的连接,一旦除了活动客户端之外还有新客户端到达,接收线程立即希望工作线程离开临界区,以便接收线程可以进入临界区并写入队列。
如何做到这一点?有什么方法可以让线程在调用 EnterCriticalSection 时必须立即强制所有其他线程离开临界区并访问临界区(我猜这是某种优先级)。
在我的代码中,工作线程始终处于关键部分。当接收线程要进入临界区时,它设置一个事件,工作线程检查这个事件并离开临界区。然后,工作线程等待直到此事件被重置并再次获得关键部分的访问权限。
我的方法正确吗?有没有更好的方法来做到这一点?
DWORD WINAPI workerThreadProcedure(LPVOID param)
{
struct node* sendBuff;
char sendBuffer[600];
while(1)
{
EnterCriticalSection(&cs);
Sleep(500);
if((WaitForSingleObject(data_available_event,0)) == WAIT_OBJECT_0 ) /*check for event*/
{
//Event is Set. Leave critical Section now
LeaveCriticalSection(&cs);
while(WaitForSingleObject(data_available_event,0) == WAIT_OBJECT_0)
{
//Waiting to get REset \r\n");
}
//REset Done
EnterCriticalSection(&cs); //again enter Critical Section.
}
//Going to pop data out
sendBuff = pop();
while(sendBuff != NULL) // while Queue is not empty
{
//sendto() some data on socket
sendBuff = pop();
}
LeaveCriticalSection(&cs);
}
return 0;
}
DWORD WINAPI receiveThreadProcedure(LPVOID param)
{
//recvfrom()
// if received Buffer is from a new Client
SetEvent(data_available_event); /* signal worker thread that data is available and now I want to write to Queue*/
struct node* cur;
char clientPort[12], detail[512], *clientIP = inet_ntoa(clientSocket.sin_addr);
int cliPort = ntohs(clientSocket.sin_port);
itoa(cliPort,clientPort,10);
strcat(clientIP," ");
strcpy(detail,clientIP);
strcat(detail,clientPort);
EnterCriticalSection(&cs);
cur =cread();
cur->data = detail;
cur->n=NULL;
push(cur);
ResetEvent(data_available_event);
LeaveCriticalSection(&cs);
}
编辑: 现在,当我运行此代码时,当新客户端到来时接收线程进入临界区,push()es 一些数据,然后重置事件,之后工作线程再次进入临界区,但随后在弹出时出现以下错误。
Master.exe 中 0x01031ba5 处的未处理异常:0xC0000005:访问冲突读取位置 0x00000000。