我正在研究Single Producer Single Consumer Problem.Here producer thread将写入列表,而消费者线程将其从列表中删除。 我有对话框,我在其中维护两个列表1.consumer列表框2.producer列表框,它将列出两个线程发布的消息。我在这里遇到奇怪的问题。这些消息是相互混淆的。消费者线程是除了消费者线程消息线程之外,还获得Producer的消息,反之亦然。
我从主线传递THREADINFO
任何机构都可以告诉我这里出了什么问题。我从主线程传递正确的线程名称,但是当涉及到生产者或消费者线程时,某些时候值会发生变化。 我在下面给出了两个帖子
typedef struct THREADINFO{
CEventQueue* pEventQueue;
HWND hWndHandle;
char* pThreadName;
}THREADINFO
DWORD WINAPI ProducerThrdFunc ( LPVOID n )
{
THREADINFO* stThreadInfoProd = (THREADINFO*)n;
char* pMsg1 = new char[100];
while(1)
{
strcpy(pMsg1,stThreadInfoProd->pThreadName);
strcat(pMsg1," Thread No:");
strcat(pMsg1,"Adding Msg");
PostMessage(stThreadInfoProd->hWndHandle,UWM_ONUPDATEPRODUCERLIST,(WPARAM)pMsg1,0);
stThreadInfoProd->pEventQueue->AddTail(pMsg1);
memset(pMsg1,0,100);
strcpy(pMsg1,stThreadInfoProd->pThreadName);
strcat(pMsg1,"Thread No:");
strcat(pMsg1,"Added Msg");
char*p = "Producer";
PostMessage(stThreadInfoProd->hWndHandle,UWM_ONUPDATEPRODUCERLIST,(WPARAM)pMsg1,0);
Sleep(3000);
}
return 0;
}
DWORD WINAPI ConsumerThrdFunc ( LPVOID n )
{
THREADINFO* stThreadInfoCons = (THREADINFO*)n;
char* pMsg = new char[100];
memset(pMsg,0,100);
while(1)
{
strcpy(pMsg,stThreadInfoCons->pThreadName);
strcat(pMsg," Thread No:");
strcat(pMsg,"Removing Msg");
PostMessage(stThreadInfoCons->hWndHandle,UWM_ONUPADTECONSUMERLIST,(WPARAM)pMsg,0);
memset(pMsg,0,100);
char *pMsg = (char*)stThreadInfoCons->pEventQueue->RemoveHead();
strcpy(pMsg,stThreadInfoCons->pThreadName);
strcat(pMsg,"Thread No:");
strcat(pMsg,"Removed Msg");
PostMessage(stThreadInfoCons->hWndHandle,UWM_ONUPADTECONSUMERLIST,(WPARAM)pMsg,0);
Sleep(3000);
}
return 0;
}
答案 0 :(得分:0)
你的THREADINFO
结构是如何构建的?在您创建结构的函数中的本地堆栈上,在堆栈的全局级别上,还是在堆上?
在THREADINFO
实例加入工作线程之前,它可能会超出范围。
答案 1 :(得分:0)
此代码存在很多问题。
在您的生产者主题中,您正在执行以下操作:
stThreadInfoProd->pEventQueue->AddTail(pMsg1);
除非AddTail很聪明,否则这是添加指向队列的指针,它不会复制字符串。然后,在您的消费者中,您正在这样做:
char *pMsg = (char*)stThreadInfoCons->pEventQueue->RemoveHead();
获取您添加到队列中的指针。这指向您用于生成器消息的缓冲区,因此当您在使用者中执行此操作时:
strcpy(pMsg,stThreadInfoCons->pThreadName);
strcat(pMsg,"Thread No:");
strcat(pMsg,"Removed Msg");
你正在覆盖制作人的缓冲区。我想你想要的更像是这样:
char *pProducerMsg = (char*)stThreadInfoCons->pEventQueue->RemoveHead();
然后以下行不会覆盖生产者的数据。
但这引入了另一个问题。在您的制作人中,您可以这样做:
stThreadInfoProd->pEventQueue->AddTail(pMsg1);
将指针添加到队列中,然后立即执行此操作:
memset(pMsg1,0,100);
strcpy(pMsg1,stThreadInfoProd->pThreadName);
strcat(pMsg1,"Thread No:");
strcat(pMsg1,"Added Msg");
覆盖缓冲区。这种覆盖几乎肯定会在消费者有机会使用消息之前发生,因此消费者将读取修改后的缓冲区,而不是您最初发送的消息。要解决这个问题,请改变生产者:
stThreadInfoProd->pEventQueue->AddTail(strdup(pMsg1));
strdup创建pMsg1指向的缓冲区内容的副本。
然后消费者需要:
char *pProducerMsg = (char*)stThreadInfoCons->pEventQueue->RemoveHead();
// do something with pProducerMsg
free (pProducerMsg); // strdup calls malloc, so a matching free is required