Производитель потребительских товаров Тема выпуска - PullRequest
0 голосов
/ 03 марта 2011

Я работаю над проблемой единственного производителя с одним потребителем. Здесь поток производителя запишет в список, а поток потребителя удалит его из списка. У меня есть диалоговое окно, в котором я поддерживаю два списка: 1. список потребителей. 2. список производителей, в котором будет перечислено сообщение, опубликованное обоими потоками. У меня возникает странная проблема. Здесь сообщения перепутаны друг с другом. также получает сообщение источника кроме потока сообщений потока потребителя и наоборот.

Я передаю 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;
}

Ответы [ 2 ]

0 голосов
/ 03 марта 2011

В этом коде много неправильного.

В ветке вашего продюсера вы делаете следующее:

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
0 голосов
/ 03 марта 2011

Как строится ваша THREADINFO структура?На локальном стеке в функции, где вы создаете структуру, на глобальном уровне стека или в куче?Возможно, экземпляр THREADINFO выходит из области действия, прежде чем он будет принят в рабочих потоках.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...