C++ Builder
| Главная | Уроки | Статьи | FAQ | Форум | Downloads | Литература | Ссылки | RXLib | Диски |

 
корректно засуспендить поток, не потеряв мутекса
Tertium
Отправлено: 30.05.2005, 23:33


Машинист паровоза

Группа: Почетный участник
Сообщений: 192



Вопрос многопоточного плана.
История, которую я хочу вам рассказать, произошла в условиях зло@#$$@го VCL. Но дело не в том.
Вот такая ситуация. Кроме основного есть потоок для связи с неким девайсом. В цикле он опрашивает девайс, периодически интересуясь состоянием нек-рых переменных, приндалежащих окну, работающему в главном потоке. Для этого он использует мутекс. И вот засада: ведь при некрых условиях снаружи происходит suspend девайсного потока, а потом опять resume. В потоке функция типа:
CODE

while(!Terminated)
{
 WaitForSingleObject(hAccessMutex,INFINITE);
 int automats_number=SetupWnd->Setup.application.automats_number;
 ReleaseMutex(hAccessMutex);
 for (int i=1;i<automats_number+1;i++)
 {
  LowLevel::Write_Data(send_data);
  if (LowLevel::Read_Data((uchar*)&m_tmp_is))
  Synchronize(UpdateValues);
 }
 Sleep(100);
}

Если поток оборвать, то, понятно он может защемить мутекс, и мы его не дождёмся. Таджа делаем так. Если снаружи определить некрую переменную thread_suspended при работающем потоке равную false, то правомерно ли изменить код так:
CODE

while(!Terminated)
{
 WaitForSingleObject(hAccessMutex,INFINITE);
 int automats_number=SetupWnd->Setup.application.automats_number;
 bool ts=SetupWnd->thread_suspended;
 ReleaseMutex(hAccessMutex);
 if (ts)
  Suspend();
 ...

}

И снаружи всё сводится к установке thread_suspended (прикрывшись мутексом) в true, и поток сам себя суспендид? И потом, откуда, когда снаружи делаем Resume, пойдёт выполнение поточной ф-ции? Начиная с "for (int i=1;i Прошу прощения конечно, за пространность, просто хочется быть уверенным. А то нигде вроде не написано, как узнать, где поток засуспендился (внутри его ф-ции) и откуда потом пошёл.
Георгий
Отправлено: 30.05.2005, 23:46


Почетный железнодорожник

Группа: Модератор
Сообщений: 874



конечно сразу возникает вопрос — "зачем поток останавливать?", но эго можно оставить на потом.

при вызове resume:
1. поток остановлен — его работа продолжается со следующей инструкции после команды остановки. в данном случае это "for(..."
2. поток работает — никаких изменений.

так что смело используй это решение — всё будет нормально.
Tertium
Отправлено: 31.05.2005, 03:42


Машинист паровоза

Группа: Почетный участник
Сообщений: 192



Стопить дабы неотжирал времени, када не нужен.

Не, началось нечто необъяснимое... Врубаться не стал и всё рефакторил. И вот, кажется, нашёл решение.
CODE
 
while(WAIT_OBJECT_0!=WaitForSingleObject(hDBConnectedEvent,100) && !Terminated);

А снаружи когда надо застопить — ResetEvent(hDBConnectedEvent) — переменная hDBConnectedEvent не та же а просто евент тот же. И после этого паузу поставить, приблизительно равной, за которое процедура потока сможет обернуться (у меня там аж 50мс) и дойти до
CODE
 
while(WAIT_OBJECT_0!=WaitForSingleObject(hDBConnectedEvent,100) && !Terminated);

Чтобы если она где-то посерёдке, мы точно дождались этого импровизированного резюма. И ясно откуда дальше пойдёт. Во как.

Вернуться в Вопросы программирования в C++Builder