Не подскажете, как отменить WaitForMultipleObjects?
Имеем кучу объектов, и WiatForMultipleObjects вызвана с параметром bWaitAll = TRUE. Но в какой-то момент надо завершить ожидание по другому событию.
Т.е. WaitForMultipleObjects реализует схему (O1 | O2 | ... | On) при bWaitAll = FALSE и (O1 & O2 & ... & On) при bWaitAll = TRUE. А мне хочется что-то типа (O1 & O2 & ... & On) | Om. Кроме как играться со временем ожидания или переводить всё на bWaitAll = TRUE ничего на ум не приходит.
Здравствуйте, 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;
}
}
}
Здравствуйте, 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 ?
Здравствуйте, 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'ами, если отработает один из объектов не возникнет ли рассинхронизации? по идее не должно, но все равно, надо проверить.
и еще раз повторю: очень похоже, что такой непростой случай возник в результате неправильного проектирования
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, то она вернет только один и флаги никогда не будут выставлены
NB>и еще раз повторю: очень похоже, что такой непростой случай возник в результате неправильного проектирования
присоединюсь. И еще дабавлю возмоджное решение. Делается синхрообъект — флаг завершения. Далее деляается waitForMultipleObjects (wait_all) с таймаутом скажем 100 мс. Проверка кода выхода (таймаут или сигнал), потом проверка на объект завершения через WaitForSingleObject без ожидания и опять в цикле на проверку объектов.
NB>ага... NB>только если несколько объектов изменит свое состояние между вызовами WaitForMultipleObjects, то она вернет только один и флаги никогда не будут выставлены
вообще — да. но только если это не manual-reset event
Здравствуйте, NightBlade, Вы писали:
Ovl>>вообще — да. но только если это не manual-reset event
NB>если это manual-reset event, то тут ваще весь этот огород городить незачем
с флагами. пусть кто событие взводит, все эти условия и обрабатывает. тут тогда достаточно будет одного объекта синхронизации
и, кстати, а причем здесь вручную оно сбрасывается или нет? важно, когда оно устанавливается
Здравствуйте, NightBlade, Вы писали:
NB>и, кстати, а причем здесь вручную оно сбрасывается или нет? важно, когда оно устанавливается
waitforobjects вызванный повторно вернет объект, который находится все ещё в сигнальном состоянии.
таким образом сбрасывая объекты по одному вручную, можно узнать кто из них был в сигнальном состоянии.
проблема будет только тогда, когда один из объектов постоянно сигналится. тогда до остальных просто не успеет дойти очередь. однако его можно второй раз и не ждать, исключая из аргументов.
Здравствуйте, 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 ничего на ум не приходит.
A>может поможет WaitForMultipleObjectsEx + QueueUserAPC ? PD>ИМХО проще MsgWaitForMultipleObjects. В нужный момент послать туда что-нибудь PostMessage...
ага... одно другого проще...
один хочет APC навернуть, другой мессаги слать...
НАХРЕНА???
есть куча типов объектов синхронизации, под которые заточены WaitForMultipleObjects и WaitForMultipleObjectsEx. зачем еще кучу других наворотов добавлять? результат-то один. не проще ли SetEvent сделать?
З.Ы. а WaitForMultipleObjectsEx с собщениями работает для совместимости с псевдомногозадачной Вынь 3.х
Здравствуйте, NightBlade, Вы писали:
NB>ага... одно другого проще... NB>один хочет APC навернуть, другой мессаги слать... NB>НАХРЕНА??? NB>есть куча типов объектов синхронизации, под которые заточены WaitForMultipleObjects и WaitForMultipleObjectsEx. зачем еще кучу других наворотов добавлять? результат-то один. не проще ли SetEvent сделать?
Прерывание ожидания через АРС — наиболее правильный способ.
Здравствуйте, NightBlade, Вы писали:
A>>может поможет WaitForMultipleObjectsEx + QueueUserAPC ? PD>>ИМХО проще MsgWaitForMultipleObjects. В нужный момент послать туда что-нибудь PostMessage...
NB>есть куча типов объектов синхронизации, под которые заточены WaitForMultipleObjects и WaitForMultipleObjectsEx. зачем еще кучу других наворотов добавлять? результат-то один. не проще ли SetEvent сделать?
Конечно проще, только это не будет решением заданного вопроса.
NB>>и еще раз повторю: очень похоже, что такой непростой случай возник в результате неправильного проектирования
T>присоединюсь. И еще дабавлю возмоджное решение. Делается синхрообъект — флаг завершения. Далее деляается waitForMultipleObjects (wait_all) с таймаутом скажем 100 мс. Проверка кода выхода (таймаут или сигнал), потом проверка на объект завершения через WaitForSingleObject без ожидания и опять в цикле на проверку объектов.
Чего-то сижу и туплю — чем такой дизайн плох. Имеем несколько источников данных, которые требуют время чтобы загрузиться (делают они это не в отдельном потоке, и большую часть времени просто ждут сообщений, но не в этом суть). Соответсвтвенно раньше было всё удобно — по загрузке эти источники выставляют флаг, мы ждём всех (bWaitAll = TRUE) какое-то время, и дальше обрабатываем те, которые выставили флаг. С одной стороны хорошо — если все источники быстренько загрузились, то немедля переходим к обработке, иначе обрабатываем по таймауту, который может быть INFINITE. Но вот потребовалось быстренько завершить все потоки (дана команда с вещами на выход), и кроме как всякие гемморои с ожиданим bWaitAll = FALSE или по 100 мс в голову не приходят. Т.е. конечно эти способы отлично подходят, но код как минимум выглядит не так читаемо — придётся писать коментарии :)
Здравствуйте, Ovl, Вы писали:
Ovl>Здравствуйте, NightBlade, Вы писали:
NB>>и, кстати, а причем здесь вручную оно сбрасывается или нет? важно, когда оно устанавливается
Ovl>waitforobjects вызванный повторно вернет объект, который находится все ещё в сигнальном состоянии. Ovl>таким образом сбрасывая объекты по одному вручную, можно узнать кто из них был в сигнальном состоянии. Ovl>проблема будет только тогда, когда один из объектов постоянно сигналится. тогда до остальных просто не успеет дойти очередь. однако его можно Ovl>второй раз и не ждать, исключая из аргументов.
Все они мануал, да ещё и TIMEOUT может быть INFINITE. Ну и тот, кто устанавливает события, ничего не знает о том, кто его ждёт. Кроме как разбивать интервал на короткие промежутки, проверяя hCancelEvent и вручную считая timeout ничего другого родить не могу.