Модераторы: ginnie, korob2001
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Win32::Daemon & WMI Notification Query, как асинхронно обрабатывать события WMI? 
:(
    Опции темы
Ramirez
  Дата 20.10.2011, 21:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 305
Регистрация: 18.1.2005
Где: Moscow, ExUSSR

Репутация: нет
Всего: 5



Доброго всем дня!

Обращаюсь к коллективному разуму, работавшему с WMI smile

Есть скрипт слушающий некие события WMI вида:

Код

my $wmi = Win32::OLE->GetObject('winmgmts:{(security)}')->ExecNotificationQuery($wql_query);
while (1) {
    my $event= $wmi->NextEvent(); # тут цикл ждет пока не произойдет событие
    warn "we have event!";  # делаем что-то полезное
}


работает абсолютно линейно, цикл ждет событие, делает что-то и опять ждет.


есть служба на базе Win32::Daemon, вида:

Код

Win32::Daemon::RegisterCallbacks( {
    start       =>  \&Callback_Start,
    running     =>  \&Callback_Running,
    stop        =>  \&Callback_Stop,
    pause       =>  \&Callback_Pause,
    continue    =>  \&Callback_Continue,
} );
Win32::Daemon::StartService( \%CONTEXT, 2000 ); # запустить службу, вызввать &Callback_Running каждые 2 секунды

# -------------------------------------------------------------------
sub Callback_Running {
    my( $event, $context ) = @_;
    if( SERVICE_RUNNING == Win32::Daemon::State() ) {
        warn ('....do something good!');
    }
}


логика работы Win32::Daemon исползует callback'и. 
процедура Callback_Running вызывается каждые 2 секунды, в ней предполагается быстро сделать небольшую часть полезной работы и вернуть управление в Win32::Daemon.
а мне необходимо слушать WMI события.
я не могу в &Callback_Running вызвать прослушивание WMI не заблокировав службу. Она будет обрабатывать мои события, но перестанет  быть управляемой и перестанет отвечать на сигналы Service Control Manager, и он решит что она висит.

как асинхронно обрабатывать события NotificationQuery из WMI?
я пробовал в &Callback_Running делать нечто вида:

Код

my $event = $wmi->NextEvent(500); # подождать события 500 миллисекунд. если события не будет $event будет пустым. 
while ($event ne "") {
    warn ('we have event!'); 
    $event = $wmi->NextEvent(500); # если в течении 500 миллисеккунд не произойдет события выйти из цикла
}


тогда, по идее, код ждет события 500-1000 миллисекунд, если не получает его, то возвращает управление в Win32::Daemon.
но у меня есть основания полагать, что:
-  это неправильный подход и часть событий, происходящих между вызовами &Callback_Running теряется.
- при неудачном стечении обстоятельств/потоке событий он никогда не выйдет из этого цикла



Поделитесь опытом/соображениями.
- как правильно в такой ситуации обрабатывать события NotificationQuery из WMI?
- ExecNotificationQuery() кеширует события если я не успеваю их забирать через NextEvent()?


Это сообщение отредактировал(а) Ramirez - 20.10.2011, 21:54
PM ICQ   Вверх
Ramirez
Дата 10.11.2011, 13:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 305
Регистрация: 18.1.2005
Где: Moscow, ExUSSR

Репутация: нет
Всего: 5



Ну что-же, поскольку внятного ответа не нашел, поделюсь своими наблюдениями smile
объект wmi, видимо, всетаки кеширует данные в ожидании вызова NextEvent(). Поэтому имеет смысл всегда вызывать NextEvent() до тех пор, пока оно не вернет пустоту.
Неизвестно, правда, сколько в этот кеш влезает и как посмотреть его состояние.

на основании наблюдений, получился рабочий код вида:

Код

Win32::Daemon::RegisterCallbacks( {
    start       =>  \&Callback_Start,
    running     =>  \&Callback_Running,
    stop        =>  \&Callback_Stop,
    pause       =>  \&Callback_Pause,
    continue    =>  \&Callback_Continue,
} );
Win32::Daemon::StartService( \%CONTEXT, 2000 ); # запустить службу, вызввать &Callback_Running каждые 2 секунды

# -------------------------------------------------------------------
sub Callback_Running {
    my( $event, $context ) = @_;
    if( SERVICE_RUNNING == Win32::Daemon::State() ) {
        my $event;
        while ($event = $wmi->NextEvent(500)) { # если нет события, ждать 500 мсек
            warn('do something!');
        }
    }
}


пока тестирую, но вроде все работает корректно, события не теряются.
PM ICQ   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Perl: Системное программирование"
korob2001
sharq
  • В этом разделе обсуждаются вопросы относящиеся только к системному программированию на Perl
  • Если ваш вопрос не относится к системному или CGI программированию, задавайте его в общем разделе
  • Если ваш вопрос относится к CGI программированию, задавайте его здесь
  • Интерпретатор Perl можно скачать здесь ActiveState, O'REILLY, The source for Perl
  • Справочное руководство "Установка perl-модулей", можно скачать здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, korob2001, sharq.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Perl: Системное программирование | Следующая тема »


 




[ Время генерации скрипта: 0.0398 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.