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