Слишком много постов было сделано к семафору - PullRequest
0 голосов
/ 07 марта 2011

Привет, мы разработали пример кода для реализации. Многочисленные проблемы с производителем и одним потребителем.

Я взял очередь и ограничил ее размер до 20. Так что я использую семафор и CrticalSection (windows api) для его защиты. Если более 20 потоков в очереди, он не будет допущен.Семафор должен защищать его.

У меня есть два метода AdddTail (добавить сообщение в очередь) и метод Remove Head (удалить сообщение из очереди) для манипулирования очередью.

Я получаю сообщение об ошибке Слишком много постов было сделано к семафору . Я не понимаю проблемы.У меня есть 20 потоков производителей с ожиданием 8000 мс и одним потребительским потоком с ожиданием 4000 мс.Я думаю, что ReleaseSemaphore вызывает проблему.

BOOL CEventQueue::AddTail(LPVOID p)
{ 

       BOOL result;
       char* pMsg = (char*)p;
       char* pMsg1 = new char[100];
       int nOffset = strlen(pMsg);

       strcpy(pMsg1,pMsg);
       strcat(pMsg1," Waiting");
       PostMessage(hWnd,UWM_ONUPDATEPRODUCERLIST,(WPARAM)pMsg1,0);
       DWORD dwWaitResult = WaitForSingleObject(handles,INFINITE);
       switch(WAIT_OBJECT_0)
       {
       case WAIT_OBJECT_0:
           {
           ::EnterCriticalSection(&m_QueueLock);
           queue.AddTail(p);
            ::LeaveCriticalSection(&m_QueueLock);
           result = ::ReleaseSemaphore(handles[SemaphoreIndex],1, NULL);
           }
           break;
       case WAIT_TIMEOUT:   
           return 0;
           break;
       }      
       if(!result)
       { /* failed */
           // caller can use ::GetLastError to determine what went wrong
           queue.RemoveTail();
          ErrorExit(_T("AddTail"));
       } /* failed */

       return result;
} // AddTail

 LPVOID result;

       switch(::WaitForMultipleObjects(2, handles, FALSE, INFINITE))
       {
            /* decode */
            case StopperIndex:   // shut down thread
              ::ExitThread(0);  // kill thread
              return NULL;      // return keeps C compiler happy

            case SemaphoreIndex: // semaphore
              ::EnterCriticalSection(&m_QueueLock);
              result = queue.RemoveHead();
              ::LeaveCriticalSection(&m_QueueLock);
              return result;

            case WAIT_TIMEOUT: // not implemented
            default:
            ASSERT(FALSE); // impossible condition
            return NULL;
            //::ReleaseSemaphore(handles[SemaphoreIndex],1, NULL);
      } /* decode */

1 Ответ

2 голосов
/ 07 марта 2011

Измените WaitForSingleObject(handles,INFINITE) на WaitForSingleObject(handles[SemaphoreIndex],INFINITE).

Измените switch(WAIT_OBJECT_0) на switch(dwWaitResult) и добавьте обработку ошибок для этого переключателя.

case StopperIndex: должен быть регистр StopperIndex + WAIT_OBJECT_0:,примените то же самое изменение к case SemaphoreIndex:

Установите максимальный уровень предупреждения компиляторов и исправьте то, о чем он предупреждает.

Правильный порядок операций:

Производитель: блокировкакритический раздел, добавление в очередь, освобождение критического раздела, выпуск семафора.

Потребитель: ожидание семафора, блокировка критического раздела, выборка из очереди, освобождение критического раздела.

Ваш код, кажется, ожидаетдля семафора как у производителя, так и у потребителя, который заходит в тупик.

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