Название: Удаление QTreeWidgetItem из вторичного потока Отправлено: astramax57 от Январь 06, 2009, 15:03 Доброго дня!
Итак, Qt 4.4.3, XP, 9-я студия. Есть QtreeWidget. В него по мере поступления сообщений из дочернего потока добавляются item-ы: Код:
Задача: необходимо, чтобы количество итемов было не больше N. Если итемов N и приходит новое сообщение, то первый итем удаляется и новое сообщение записывается в конец списка. Удалять собираюсь так: Код: delete messages_from_topTV->TakeTopLevelItem(0); Если пытаться что-то удалять из вторичного потока (т.е. из функции, добавляющей сообщения) то вылетает исключение. Пытался так Код: QMetaObject::invokeMethod(messages_from_topTV, "takeTopLevelItem",Qt::QueuedConnection, Q_ARG(int, 0)); не работает, возвращает false. Да и память будет теряться, т.к. я не вызываю delete Пытался блокировать сигналы (blockSignals) на время удаления - тоже исключения. Может кто-нибудь подскажет решение. Название: Re: Удаление QTreeWidgetItem из вторичного потока Отправлено: Dendy от Январь 06, 2009, 16:05 Гуёвые классы лучше использовать только из главного потока. QueuedConnection отрабатывает мгновенно и ничего не возвращает. Используйте BlockingQueuedConnection для синхронного вызова. Только убедитесь, что вызываемый метод обьявлен как слот.
Название: Re: Удаление QTreeWidgetItem из вторичного потока Отправлено: Dendy от Январь 06, 2009, 16:09 Да и память будет теряться, т.к. я не вызываю delete BlockingQueuedConnection может возвращать значение, которое вы сможете удалить через delete. Главное убедиться что этот указатель после take() оказался для остальных потерян. Название: Re: Удаление QTreeWidgetItem из вторичного потока Отправлено: astramax57 от Январь 06, 2009, 17:11 Скорее всего дело в том, что taketoplevelitem это не слот, а обычный метод.
Поэтому invokemethod и возвращает false. Как быть? Я пробовал вариант, когда удаление "лишних" итемов производится в слоте, навешенном на какой-нибудь сигнал QTreeWidget. Но проблема осталась: например я использую слот, подключенный к currentItemChanged. Если я меняю currentitem не программно (щелкаю мышкой), все работает, т.к. слот работает в основном ГУИ-потоке. А вот если я программно вызываю messages_from_topTV->setCurrentItem, то сыпятся исключения, т.к. слот работает во вторичном потоке. Название: Re: Удаление QTreeWidgetItem из вторичного потока Отправлено: Dendy от Январь 06, 2009, 17:47 Всё верно сыпется, если в наследнике QWidget явно не указано, что метод потокобезопастный - значит его можно вызывать только из основного потока. Попытайтесь отвязать внешний вид программы от её данных. Если вы завязались с потоками, то вам сам Бог велел использовать QTreeView вместо QTreeWidget.
Название: Re: Удаление QTreeWidgetItem из вторичного потока Отправлено: astramax57 от Январь 06, 2009, 18:44 Пробую Qtreeview + своя модель, унаследованная от QAbstractItemModel.
Приведенный в первом посте код меняется на Код: quint32 module_id; removeRow принадлежит QAbstractItemModel Код: inline bool QAbstractItemModel::removeRow(int arow, const QModelIndex &aparent) а removeRows реализована у меня в модели как Код: bool message_model::removeRows(int position, int rows, const QModelIndex &parent) и опять исключения в функции size контейнера qlist. Поскольку все методы qlist реентерабельны, мне нужно защищать сам список мьютексом, так? Название: Re: Удаление QTreeWidgetItem из вторичного потока Отправлено: Dendy от Январь 06, 2009, 19:54 Что-то мне подсказывает что так использовать модель нельзя. Модель - это интерфейс для доступа к данным из GUI классов. Она тоже должна работать в основном потоке. В другой поток можно вынести операции по работе с самими данными. Модель же должна только информировать о том что данные изменились.
Название: Re: Удаление QTreeWidgetItem из вторичного потока Отправлено: SABROG от Январь 06, 2009, 20:38 А можно позырить метод QThread::run() и участок где он вызывается ?
Название: Re: Удаление QTreeWidgetItem из вторичного потока Отправлено: astramax57 от Январь 06, 2009, 21:22 А можно позырить метод QThread::run() и участок где он вызывается ? я использую boost::thread. Может быть дело в этом? А как грамотно использовать модель? Я в кьюте полный чайник. Ткните в пример плз Название: Re: Удаление QTreeWidgetItem из вторичного потока Отправлено: SABROG от Январь 06, 2009, 22:57 я использую boost::thread. Может быть дело в этом? Попробуй на QThread протести и посмотри в сторону QApplication::postEvent(). Название: Re: Удаление QTreeWidgetItem из вторичного потока Отправлено: vaprele07 от Январь 07, 2009, 09:22 QThreadStorage + QCache в ассистенте даже пример есть!
Название: Re: Удаление QTreeWidgetItem из вторичного потока Отправлено: astramax57 от Апрель 08, 2009, 09:32 Проблему давно решил, надо и отписаться для приличия.
Я пытался удалять QTreeWidgetItem из вторичного потока, но это полбеды. Я еще их и добавлял в QTreeWidget не из гуи-потока. Проблему решил с помощью CustomEvent, то есть при поступлении нового сообщения из вторичного потока я ставлю в очередь обработки новое событие (postEvent), а в гуи потоке, когда вызовется CustomEvent, я добавляю новый QTreeWidgetItem и при необходимости удаляю старые. Спасибо всем ответившим! |