cancel WaitForMultipleObjects
От: MTatarnikov  
Дата: 07.06.06 07:41
Оценка:
Добрый день.

Не подскажете, как отменить WaitForMultipleObjects?

Имеем кучу объектов, и WiatForMultipleObjects вызвана с параметром bWaitAll = TRUE. Но в какой-то момент надо завершить ожидание по другому событию.

Т.е. WaitForMultipleObjects реализует схему (O1 | O2 | ... | On) при bWaitAll = FALSE и (O1 & O2 & ... & On) при bWaitAll = TRUE. А мне хочется что-то типа (O1 & O2 & ... & On) | Om. Кроме как играться со временем ожидания или переводить всё на bWaitAll = TRUE ничего на ум не приходит.


Спасибо.

Миша.
Re: cancel WaitForMultipleObjects
От: Ovl Россия  
Дата: 07.06.06 08:06
Оценка:
Здравствуйте, MTatarnikov, Вы писали:

MT>Добрый день.


MT>Не подскажете, как отменить WaitForMultipleObjects?


MT>Имеем кучу объектов, и WiatForMultipleObjects вызвана с параметром bWaitAll = TRUE. Но в какой-то момент надо завершить ожидание по другому событию.


MT>Т.е. WaitForMultipleObjects реализует схему (O1 | O2 | ... | On) при bWaitAll = FALSE и (O1 & O2 & ... & On) при bWaitAll = TRUE. А мне хочется что-то типа (O1 & O2 & ... & On) | Om. Кроме как играться со временем ожидания или переводить всё на bWaitAll = TRUE ничего на ум не приходит.



MT>Спасибо.


MT>Миша.



а если попробовать (O1 | O2 | ... | On | Om), и по событию выставлять флаги, после чего запускать процедуру, когда либо Om произошло, либо все флаги для O1..On выставлены



bool flags[n];
while(true) {
   ret = WaitForMultipleObjects(O1 | O2 | ... | On | Om);
   if (ret == Om) {
      doWork();
      break;
   } else if (ret == TIMEOUT) {
      break;
   } else {
      flags[ret] = true;
      if (flags.isAllSet()) {
         doWork();
         break;
      } 
   }
}
Read or Die!
Как правильно задавать вопросы
Как правильно оформить свой вопрос
Автор: anvaka
Дата: 15.05.06
Re: cancel WaitForMultipleObjects
От: altarvic  
Дата: 07.06.06 08:16
Оценка: 1 (1) +2
Здравствуйте, MTatarnikov, Вы писали:

MT>Добрый день.


MT>Не подскажете, как отменить WaitForMultipleObjects?


MT>Имеем кучу объектов, и WiatForMultipleObjects вызвана с параметром bWaitAll = TRUE. Но в какой-то момент надо завершить ожидание по другому событию.


MT>Т.е. WaitForMultipleObjects реализует схему (O1 | O2 | ... | On) при bWaitAll = FALSE и (O1 & O2 & ... & On) при bWaitAll = TRUE. А мне хочется что-то типа (O1 & O2 & ... & On) | Om. Кроме как играться со временем ожидания или переводить всё на bWaitAll = TRUE ничего на ум не приходит.



MT>Спасибо.


MT>Миша.


может поможет WaitForMultipleObjectsEx + QueueUserAPC ?
Re: cancel WaitForMultipleObjects
От: NightBlade Россия  
Дата: 07.06.06 08:20
Оценка:
Здравствуйте, MTatarnikov, Вы писали:

MT>Т.е. WaitForMultipleObjects реализует схему (O1 | O2 | ... | On) при bWaitAll = FALSE и (O1 & O2 & ... & On) при bWaitAll = TRUE. А мне хочется что-то типа (O1 & O2 & ... & On) | Om. Кроме как играться со временем ожидания или переводить всё на bWaitAll = TRUE ничего на ум не приходит.


задумайтесь, а действительно ли так надо? может быть спроектировать все по-другому? если ожидаемые объекты изменяются вручную (события, семафоры) и ждущий поток один (или условия ожидания для нескольких потоков одинаковые), то надо просто несколько событий заменить на одно.

если действительно надо делать такие сложные условия из ожидания, то готовьтесь к гемморою.
вижу два решения:
1. создается отдельный поток который ждет (O1 & O2 & ... & On). по выходу из ожидания взводит событие (например) Е. основной поток ждет Е | Om
2. ставите bWaitAll = FALSE, после выхода из ожидания анализируете, по какому объекту был выход, и если надо вновь входите в ожидание с новыми условиями (выбросив отработанный объект). но здесь есть нюанс: пока выполняется код между Wait'ами, если отработает один из объектов не возникнет ли рассинхронизации? по идее не должно, но все равно, надо проверить.

и еще раз повторю: очень похоже, что такой непростой случай возник в результате неправильного проектирования
Все вопросы на nightblade@inbox.ru
Re[2]: cancel WaitForMultipleObjects
От: NightBlade Россия  
Дата: 07.06.06 08:29
Оценка:
bool flags[n];
while(true) {
   ret = WaitForMultipleObjects(O1 | O2 | ... | On | Om);
   if (ret == Om) {
      doWork();
      break;
   } else if (ret == TIMEOUT) {
      break;
   } else {
      flags[ret] = true;
      if (flags.isAllSet()) {
         doWork();
         break;
      } 
   }
}


ага...
только если несколько объектов изменит свое состояние между вызовами WaitForMultipleObjects, то она вернет только один и флаги никогда не будут выставлены
Все вопросы на nightblade@inbox.ru
Re[2]: cancel WaitForMultipleObjects
От: Terranozavr  
Дата: 07.06.06 08:35
Оценка:
NB>и еще раз повторю: очень похоже, что такой непростой случай возник в результате неправильного проектирования

присоединюсь. И еще дабавлю возмоджное решение. Делается синхрообъект — флаг завершения. Далее деляается waitForMultipleObjects (wait_all) с таймаутом скажем 100 мс. Проверка кода выхода (таймаут или сигнал), потом проверка на объект завершения через WaitForSingleObject без ожидания и опять в цикле на проверку объектов.
Re[3]: cancel WaitForMultipleObjects
От: Ovl Россия  
Дата: 07.06.06 08:40
Оценка:
Здравствуйте, NightBlade, Вы писали:

NB>
NB>bool flags[n];
NB>while(true) {
NB>   ret = WaitForMultipleObjects(O1 | O2 | ... | On | Om);
NB>   if (ret == Om) {
NB>      doWork();
NB>      break;
NB>   } else if (ret == TIMEOUT) {
NB>      break;
NB>   } else {
NB>      flags[ret] = true;
NB>      if (flags.isAllSet()) {
NB>         doWork();
NB>         break;
NB>      } 
NB>   }
NB>}
NB>


NB>ага...

NB>только если несколько объектов изменит свое состояние между вызовами WaitForMultipleObjects, то она вернет только один и флаги никогда не будут выставлены

вообще — да. но только если это не manual-reset event
Read or Die!
Как правильно задавать вопросы
Как правильно оформить свой вопрос
Автор: anvaka
Дата: 15.05.06
Re[4]: cancel WaitForMultipleObjects
От: NightBlade Россия  
Дата: 07.06.06 08:53
Оценка:
Ovl>вообще — да. но только если это не manual-reset event

если это manual-reset event, то тут ваще весь этот огород городить незачем
Все вопросы на nightblade@inbox.ru
Re[5]: cancel WaitForMultipleObjects
От: Ovl Россия  
Дата: 07.06.06 08:56
Оценка:
Здравствуйте, NightBlade, Вы писали:

Ovl>>вообще — да. но только если это не manual-reset event


NB>если это manual-reset event, то тут ваще весь этот огород городить незачем


какой огород?
Read or Die!
Как правильно задавать вопросы
Как правильно оформить свой вопрос
Автор: anvaka
Дата: 15.05.06
Re[6]: cancel WaitForMultipleObjects
От: NightBlade Россия  
Дата: 07.06.06 09:04
Оценка:
Ovl>какой огород?

с флагами. пусть кто событие взводит, все эти условия и обрабатывает. тут тогда достаточно будет одного объекта синхронизации
и, кстати, а причем здесь вручную оно сбрасывается или нет? важно, когда оно устанавливается
Все вопросы на nightblade@inbox.ru
Re[7]: cancel WaitForMultipleObjects
От: Ovl Россия  
Дата: 07.06.06 09:11
Оценка:
Здравствуйте, NightBlade, Вы писали:

NB>и, кстати, а причем здесь вручную оно сбрасывается или нет? важно, когда оно устанавливается


waitforobjects вызванный повторно вернет объект, который находится все ещё в сигнальном состоянии.
таким образом сбрасывая объекты по одному вручную, можно узнать кто из них был в сигнальном состоянии.
проблема будет только тогда, когда один из объектов постоянно сигналится. тогда до остальных просто не успеет дойти очередь. однако его можно второй раз и не ждать, исключая из аргументов.
Read or Die!
Как правильно задавать вопросы
Как правильно оформить свой вопрос
Автор: anvaka
Дата: 15.05.06
Re: cancel WaitForMultipleObjects
От: mr.pavel Россия  
Дата: 07.06.06 09:17
Оценка:
Пример реализации этого есть в Рихтере

Здравствуйте, MTatarnikov, Вы писали:

MT>Добрый день.


MT>Не подскажете, как отменить WaitForMultipleObjects?


MT>Имеем кучу объектов, и WiatForMultipleObjects вызвана с параметром bWaitAll = TRUE. Но в какой-то момент надо завершить ожидание по другому событию.


MT>Т.е. WaitForMultipleObjects реализует схему (O1 | O2 | ... | On) при bWaitAll = FALSE и (O1 & O2 & ... & On) при bWaitAll = TRUE. А мне хочется что-то типа (O1 & O2 & ... & On) | Om. Кроме как играться со временем ожидания или переводить всё на bWaitAll = TRUE ничего на ум не приходит.



MT>Спасибо.


MT>Миша.
Re[2]: cancel WaitForMultipleObjects
От: NightBlade Россия  
Дата: 07.06.06 09:34
Оценка:
MP>Пример реализации этого есть в Рихтере

извините за оффтоп, но, как вы думаете, у скольких программистов есть Рихтер?
Все вопросы на nightblade@inbox.ru
Re[2]: cancel WaitForMultipleObjects
От: Pavel Dvorkin Россия  
Дата: 07.06.06 10:11
Оценка:
Здравствуйте, altarvic, Вы писали:

A>Здравствуйте, MTatarnikov, Вы писали:


A>может поможет WaitForMultipleObjectsEx + QueueUserAPC ?


ИМХО проще MsgWaitForMultipleObjects. В нужный момент послать туда что-нибудь PostMessage...
With best regards
Pavel Dvorkin
Re[3]: cancel WaitForMultipleObjects
От: NightBlade Россия  
Дата: 07.06.06 11:35
Оценка:
A>может поможет WaitForMultipleObjectsEx + QueueUserAPC ?
PD>ИМХО проще MsgWaitForMultipleObjects. В нужный момент послать туда что-нибудь PostMessage...

ага... одно другого проще...
один хочет APC навернуть, другой мессаги слать...
НАХРЕНА???
есть куча типов объектов синхронизации, под которые заточены WaitForMultipleObjects и WaitForMultipleObjectsEx. зачем еще кучу других наворотов добавлять? результат-то один. не проще ли SetEvent сделать?
З.Ы. а WaitForMultipleObjectsEx с собщениями работает для совместимости с псевдомногозадачной Вынь 3.х
Все вопросы на nightblade@inbox.ru
Re[4]: cancel WaitForMultipleObjects
От: TarasCo  
Дата: 07.06.06 11:37
Оценка:
Здравствуйте, NightBlade, Вы писали:

NB>ага... одно другого проще...

NB>один хочет APC навернуть, другой мессаги слать...
NB>НАХРЕНА???
NB>есть куча типов объектов синхронизации, под которые заточены WaitForMultipleObjects и WaitForMultipleObjectsEx. зачем еще кучу других наворотов добавлять? результат-то один. не проще ли SetEvent сделать?

Прерывание ожидания через АРС — наиболее правильный способ.
Да пребудет с тобою сила
Re[5]: cancel WaitForMultipleObjects
От: NightBlade Россия  
Дата: 07.06.06 12:25
Оценка:
TC>Прерывание ожидания через АРС — наиболее правильный способ.

он правильный, только в том случае, когда АРС нужен. а лепить функцию, которая ничего не делает, а только косвенно ожидание прерывает — изврат
Все вопросы на nightblade@inbox.ru
Re[4]: cancel WaitForMultipleObjects
От: altarvic  
Дата: 07.06.06 12:30
Оценка:
Здравствуйте, NightBlade, Вы писали:

A>>может поможет WaitForMultipleObjectsEx + QueueUserAPC ?

PD>>ИМХО проще MsgWaitForMultipleObjects. В нужный момент послать туда что-нибудь PostMessage...

NB>есть куча типов объектов синхронизации, под которые заточены WaitForMultipleObjects и WaitForMultipleObjectsEx. зачем еще кучу других наворотов добавлять? результат-то один. не проще ли SetEvent сделать?


Конечно проще, только это не будет решением заданного вопроса.
Re[3]: cancel WaitForMultipleObjects
От: MTatarnikov  
Дата: 08.06.06 00:25
Оценка:
Здравствуйте, Terranozavr, Вы писали:


NB>>и еще раз повторю: очень похоже, что такой непростой случай возник в результате неправильного проектирования


T>присоединюсь. И еще дабавлю возмоджное решение. Делается синхрообъект — флаг завершения. Далее деляается waitForMultipleObjects (wait_all) с таймаутом скажем 100 мс. Проверка кода выхода (таймаут или сигнал), потом проверка на объект завершения через WaitForSingleObject без ожидания и опять в цикле на проверку объектов.




Чего-то сижу и туплю — чем такой дизайн плох. Имеем несколько источников данных, которые требуют время чтобы загрузиться (делают они это не в отдельном потоке, и большую часть времени просто ждут сообщений, но не в этом суть). Соответсвтвенно раньше было всё удобно — по загрузке эти источники выставляют флаг, мы ждём всех (bWaitAll = TRUE) какое-то время, и дальше обрабатываем те, которые выставили флаг. С одной стороны хорошо — если все источники быстренько загрузились, то немедля переходим к обработке, иначе обрабатываем по таймауту, который может быть INFINITE. Но вот потребовалось быстренько завершить все потоки (дана команда с вещами на выход), и кроме как всякие гемморои с ожиданим bWaitAll = FALSE или по 100 мс в голову не приходят. Т.е. конечно эти способы отлично подходят, но код как минимум выглядит не так читаемо — придётся писать коментарии :)
Re[8]: cancel WaitForMultipleObjects
От: MTatarnikov  
Дата: 08.06.06 00:44
Оценка:
Здравствуйте, Ovl, Вы писали:

Ovl>Здравствуйте, NightBlade, Вы писали:


NB>>и, кстати, а причем здесь вручную оно сбрасывается или нет? важно, когда оно устанавливается


Ovl>waitforobjects вызванный повторно вернет объект, который находится все ещё в сигнальном состоянии.

Ovl>таким образом сбрасывая объекты по одному вручную, можно узнать кто из них был в сигнальном состоянии.
Ovl>проблема будет только тогда, когда один из объектов постоянно сигналится. тогда до остальных просто не успеет дойти очередь. однако его можно
Ovl>второй раз и не ждать, исключая из аргументов.



Все они мануал, да ещё и TIMEOUT может быть INFINITE. Ну и тот, кто устанавливает события, ничего не знает о том, кто его ждёт. Кроме как разбивать интервал на короткие промежутки, проверяя hCancelEvent и вручную считая timeout ничего другого родить не могу.

Миша.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.