Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: WinAPI и системное программирование > Использование RegisterWaitForSingleObject


Автор: Riply 29.3.2007, 22:45
Здравствуйте !
Задача такая: отслеживать неоднократное "срабатывание" большого кол-ва объектов.
Пытаюсь воспользоваться сабжевой функцией и (как всегда) встречаю проблемы.
Допустим, мы решили поступить так:
Вызываем ее с неким флагом (не WT_EXECUTEINWAITTHREAD т.к. CallBack может занять некоторое время),
и с CallBack, примерно такого вида:
procedure WaitObjectCallBack(pParam: Pointer; TimerOrWaitFired: Boolean); stdcall;
begin
 with PWaitThreadParam(pParam)^ do // WaitThreadParam - нами определенная стуктура.
  try
   ResetEvent(hEvent); // Здесь hEvent - Handle нашего события, которого ждали.

Этот вариант плох тем, что WaitObjectCallBack может быть вызвана 138 раз, 
прежде чем мы успеем вызвать ResetEvent. smile
Вариант второй:
Вызываем ее с флагом WT_EXECUTEONLYONCE.
Здесь все работает, но есть очень большое "но".
После каждого удачного вызова WaitObjectCallBack, мы должны
снимать регистрацию нашего события ( UnregisterWait ) и заново его регистрировать. 
А мне кажется, что это вряд ли способствует оптимальному использованию ресурсов smile
Как бы исхитриться и остановиться на первом варианте, 
но с одним вызовом WaitObjectCallBack для каждого срабатывания нашего события ?
P.S. Создать некий индикатор "повторности вызова" и проверять его - (как мне кажется) не выход.

Автор: bems 30.3.2007, 00:19
Трудно понять чего именно ты хочешь, но прискну предположить что тебе поможет событие с автосбросом. Тогда ResetEvent вызывается до вызова твоего калбека

Автор: Riply 30.3.2007, 01:11
> bems
>"Трудно понять чего именно ты хочешь"
К сожалению, мои объяснения часто получаются сумбурными. :(
Попробую еще раз.
Есть n объектов. Их количество в процессе работы меняется и может оказаться
больше чем MAXIMUM_WAIT_OBJECTS. Нужно при "срабатывании"
любого из них, например, активизировать нить для обработки(или напрямую что-то выполнить) 
и вернуться к ожиданию.   
Как мне кажется, что RegisterWaitForSingleObject подходит для этого.
"Автосбрасываемый" Event - решение хорошее, но, в данном случае, не подходит :(
Т.к. WaitForMultipleObjects, которая внутри RegisterWaitForSingleObject,
(точнее одна из них) может не успеть сработать. Например, если в 
данный момент времени "основная" нить RegisterWaitForSingleObject, чем-то занята.

Автор: bems 30.3.2007, 02:46
Цитата(Riply @  30.3.2007,  01:11 Найти цитируемый пост)
"Автосбрасываемый" Event - решение хорошее, но, в данном случае, не подходит :(
Т.к. WaitForMultipleObjects, которая внутри RegisterWaitForSingleObject,
(точнее одна из них) может не успеть сработать. Например, если в 
данный момент времени "основная" нить RegisterWaitForSingleObject, чем-то занята.


Нить, кторая вызвала  RegisterWaitForSingleObject будет выполнять твою функцию только если указан флаг WT_EXECUTEINWAITTHREAD. В первом посте ты отказался от этого флага следовательно от (не)занятости вызывающего потока колбэк не зависит, а выполняться он будет в потоке, управляемом системой (если один колбэк уже выполняется, то система предоставит другой поток).
"WaitForMultipleObjects, которая внутри RegisterWaitForSingleObject" вызывается не потоком, который вызвал RegisterWaitForSingleObject, а каким-то другим (ты его вообще напрямую не создаешь)

Относительно события с автосбросом, то это более првильный вариант, т.к. в описании функции можно найти это:
Цитата

Note that you should not pulse an event object passed to RegisterWaitForSingleObject, because the wait thread might not detect that the event is signaled before it is reset. You should not register a an object that remains signaled (such as a manual reset event or terminated process) unless you set the WT_EXECUTEONLYONCE or WT_EXECUTEINWAITTHREAD flag.
Поскольку ни один из этих флагов тебе не подходит, можно сделать вывод, что если это событие - то только с автосбросом

Цитата(Riply @  30.3.2007,  01:11 Найти цитируемый пост)
WaitForMultipleObjects, которая внутри RegisterWaitForSingleObject,(точнее одна из них) может не успеть сработать

наоборот - гарантия вызова колбека для каждого изменения состояния объекта
Другой вопрос - реентерабельна ли твоя колбек-функция. Например это 
with PWaitThreadParam(pParam)^ 
намекает на неприятности, но все конечно зависит от того, что внутри with-блока



Короче вырыжаясь: при событии с автосбросом функция вызывается гарантировано каждый раз, но потенцияльно работает в нескольких потоках одновременно, и тебе решать как нужно (и нужно ли) управляться из нее с общими ресурсами

Автор: Riply 30.3.2007, 16:05
Большое спасибо за детальные разъяснеия.
После них, многое встало на свои места.
P.S.
 Очередной раз вынуждена признать, 
 что утверждение "подумать - иногда, не вредно" - истинно smile 

Автор: bems 31.3.2007, 00:37
Цитата(Riply @  30.3.2007,  16:05 Найти цитируемый пост)
вынуждена 
ой...
Цитата(bems @  30.3.2007,  02:46 Найти цитируемый пост)
ты отказался от
за это извини, мне очень стыдно...
 smile  smile 


Цитата(Riply @  30.3.2007,  16:05 Найти цитируемый пост)
Очередной раз вынуждена признать, 
 что утверждение "подумать - иногда, не вредно" - истинно 
почитать МыСыДыНы тоже полезно...  smile

Добавлено через 6 минут и 57 секунд
Хоть помогло?

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

Автор: Riply 31.3.2007, 02:41
bems, 
Цитата

за это извини, мне очень стыдно...

"К иcкусству, котрое я в данный момент представляю, это не имеет никакого отношения"
(с) (Иван Васильевич меняет профессию).   smile 
Цитата

почитать МыСыДыНы тоже полезно...
 Да... уж...   smile 
Цитата

Хоть помогло?

Да. Спасибо. Как ни странно, но работает. Бывает же smile 
Цитата

Если проблемы продолжаются - дай больше кода, разберемся по контексту

Пока нерешаемых самостоятельно не возникло, но пользуясь случаем, вдогонку, еще один вопрос:
После окончания работы с пулом (окончание - все, что надо отловили, все объекты "сняли с регистрации"),
остается "висеть" несколько нитей (количество зависит от интенсивности работы пула и кол-ва объектов).
Существует ли способ их завершить ? Или часть из них так и останется до завершения процесса ?
P.S. Не варварским способом типа TerminateThread, а объяснить системе, что они больше не нужны  smile 

Автор: bems 31.3.2007, 03:09
После вызова  UnregisterWait/UnregisterWaitEx остаются? Тогда наверное это запас на будущее или не завершенный "естественным" путем колбэк

тогда уж не знаю...

Автор: Riply 31.3.2007, 23:50
Цитата(bems @  31.3.2007,  03:09 Найти цитируемый пост)
После вызова  UnregisterWait/UnregisterWaitEx остаются? Тогда наверное это запас на будущее или не завершенный "естественным" путем колбэк

UnregisterWaitEx вызывался параметром INVALID_HANDLE_VALUE
В "колбэке" только Sleep(10);
Кроме одного исчезают минут через пять.
Будем считать что система очень запаслива  smile 
Еще раз спаибо.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)