| 
| 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);
 
 | 
 Чтобы если она где-то посерёдке, мы точно дождались этого импровизированного резюма. И ясно откуда дальше пойдёт. Во как.
 |  
|  |  |