Russian Qt Forum
Ноябрь 24, 2024, 23:40 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: CreateEvent, WaitForSingleObject и Qt  (Прочитано 9078 раз)
burunduk
Гость
« : Ноябрь 29, 2007, 13:53 »

Получилось только так сделать:

1. Создал событие userEvent = CreateEvent(NULL, FALSE, FALSE, NULL)
2. Установил QTimer с таймаутом 0  и в слоте который он вызывает пишу
       DWORD res = WaitForSingleObject(userEvent, 50);
       if (res == WAIT_OBJECT_0) { ...
3. При каком-то условии в программе устанавливаю сигнальное состояние для события: SetEvent(userEvent)

Можно ли обойтись без таймера и WaitForSingleObject чтобы например выхватывать событие в очереди сообщений ?

Пробовал для QApplication использовать winEventFilter(),  event()  - нигде не видно, только ловится с ожиданием через WaitForSingleObject.

З.Ы.   спросите зачем понадобилось, когда есть сигналы-слоты, для взаимодействия со сторонним SDK
Записан
Alex03
Гость
« Ответ #1 : Ноябрь 29, 2007, 14:40 »

Похоже Вы несколько путаетесь в понятиях.
1. winEventFilter() отлавливает виндовые сообщения, которые достаются из очереди например PeekMessage()/GetMessage().
2. Виндовый Event - это Виндовый объект синхронизации, один из нескольких (типа Mutex, Semaphore, Process/Thread и т.д.) Именно эти объекты обслуживаются [Msg]WaitFor{Single|Multiple}Object[Ex]() набором функций.
3. Qt event - кроссплатформенноя  абстракция.

Если я правильно понял то:
Другой процесс или драйвер меняет состояние эвента, видимо поименованного, и это дело надо отловить?
Для этого хочется влезть в внутренний цикл Qt, и чёб оно от туда сигналило?

В 3.х.х искал - не нашел.
По идее очень полезная фича была бы, правда ОС-зависимая.
В винде бы QApplication-у говорить хэндлы и слоты им соответствующие. А Qt бы эти хэндлы скармливала в какойнить MsgWaitForMultipleObjects() во внутреннем цикле.

В линуксе работать с железом помагает QSocketNotifier.

Записан
burunduk
Гость
« Ответ #2 : Ноябрь 29, 2007, 17:21 »

Да, Вы правильно поняли

Другими словами вместо стандартной ф-ции обратного вызова я могу также создать виндовый Event и передать его handle в SDK. Когда событие наступает, SDK устройства этот Event переводит в сигнальное состояние. Я хочу поймать это и вызвать сигнал у своего объекта. Собственно всё.

Можно было бы и через call-back ф-цию,  но так как её прототип жестко задан в SDK, максимум что я могу - это вызвать статический метод у класса. Cигнал оттудова не вызовешь, какому экземпляру класса принадлежит не узнаешь и т.д. В случае же с виндовыми Event'ами можно их хендлы позапоминать и резолвить к чему же он относится. CustomData у call-back ф-ции  нету :(

Спасибо что просветили, что это совсем разные объекты :)   Я думал что СreateEvent помещает событие в стандартную виндовую очередь.
Записан
Tonal
Гость
« Ответ #3 : Ноябрь 30, 2007, 11:32 »

Для таких call-back-ов обычно используют статическую функцию класса + статический указатель на экземпляр обработчик.
Примерно так:
Код:
//Заголовок:
class Notifer : QObject {
  Q_OBJECT
public:
  Notifer(QObject parent = 0)
  ~Notifer()
public signals:
  void notify(args...);
private:
  void doNotify(args...);
  static void callBack(args...)
  static Notifer* self;
}
//Реализация
Notifer::self = 0;
Notifer::Notifer(QObject parent) : QObject(parent) {
  self = this;
  InitSDKСallBack(callBack);
}
~Notifer::Notifer() {
  self = 0;
}
Notifer::callBack(args...) {
  self->doNotify(args...);
}
Notifer::doNotify(args...) {
  emit notify(args...);
}
Инициализацию, состав и типы аргументов замени на свои.

Ну а если хочешь всё-таки использовать виндовый Event, то создавай отдельный поток и там его слушай, иначе заморозишь весь GUI.
Да, можно в принципе WaitForSingleObject пользовать и в основном потоке, но тогда таймаут ему выставлять лучше в 0 ну и проверять - было событие, или не было.
« Последнее редактирование: Ноябрь 30, 2007, 11:36 от Tonal » Записан
Alex03
Гость
« Ответ #4 : Ноябрь 30, 2007, 14:38 »

Можно было бы и через call-back ф-цию,  но так как её прототип жестко задан в SDK, максимум что я могу - это вызвать статический метод у класса. Cигнал оттудова не вызовешь, какому экземпляру класса принадлежит не узнаешь и т.д. В случае же с виндовыми Event'ами можно их хендлы позапоминать и резолвить к чему же он относится. CustomData у call-back ф-ции  нету Грустный
Не очень понял. Вы Event'ов в SDK можете передать много, а callback всего один (да ещё и без CustomData)?
Если так, то во первых это кривое SDK, а во вторых позволяет ли SDK параллельно использовать и Event-ы и callback?
Если Да то в том же callback-е можно проверить все переданные в SDK Event-ы, и соответственно распознать что за событие...

Далее надо сообщить о событии приложению.
SDK ж выполняется в отдельном потоке? Значит напрямую сигнал не засигналишь, слот не вызовешь (по крайней мере не любой). Тут просится какойнить QCoreApplication::postEvent(). Ну и если события (callback-и) могут валиться часто, то это тоже надо корректно обрабатывать, дабы не вводить приложение в ступор.
Записан
burunduk
Гость
« Ответ #5 : Декабрь 10, 2007, 11:00 »

спасибо, tonal
вот вернулся всё-таки к callback'ам, пробовал через обычные winEvent но они иногда долго идут, точнее пока окно таскаю по экрану - вообще не идут ...  И Ваш пример кода очень помог, не знал что так можно callback'и спрятать  Улыбающийся

Для таких call-back-ов обычно используют статическую функцию класса + статический указатель на экземпляр обработчик.
Примерно так:
Код:
//Заголовок:
class Notifer : QObject {
  Q_OBJECT
public:
  Notifer(QObject parent = 0)
  ~Notifer()
public signals:
  void notify(args...);
private:
  void doNotify(args...);
  static void callBack(args...)
  static Notifer* self;
}
//Реализация
Notifer::self = 0;
Notifer::Notifer(QObject parent) : QObject(parent) {
  self = this;
  InitSDKСallBack(callBack);
}
~Notifer::Notifer() {
  self = 0;
}
Notifer::callBack(args...) {
  self->doNotify(args...);
}
Notifer::doNotify(args...) {
  emit notify(args...);
}
Инициализацию, состав и типы аргументов замени на свои.

Ну а если хочешь всё-таки использовать виндовый Event, то создавай отдельный поток и там его слушай, иначе заморозишь весь GUI.
Да, можно в принципе WaitForSingleObject пользовать и в основном потоке, но тогда таймаут ему выставлять лучше в 0 ну и проверять - было событие, или не было.
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.048 секунд. Запросов: 20.