Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > С/С++: Кроссплатформенное программирование, Qt/Gtk+/wxWidgets > moveToThread


Автор: xbarmaglot 22.4.2013, 20:43
У меня объект создавался в главном потоке и подключались его сигнады к слотам родителя.
Но понадобилось вынести создание объекта в отдельный поток, т.к. занимало много времени.
Из вторичного потока, после создания объекта, я его перемещаю в главный поток с помощью сигнала
где он и хранится. В слоте я получаю созданный во вторичном потоке QSharedPointer<MyObject>,
подключаю сигналы к слотам и сохраняю объект в карте.

Но после переноса создания объекта в отдельный поток перестали срабатывать сигналы.
Хотя QObject::connect отрабатывает без ошибок.

1.Связано ли это с тем, что объект создавался в отдельном потоке ?
2.Поможет ли мне moveToThread? Просто он выдает отладочное сообщение с ошибкой.
3.Если еще какие способы решения моей проблемы ?

Автор: kolesnle 22.4.2013, 22:42
Цитата(xbarmaglot @  22.4.2013,  20:43 Найти цитируемый пост)
2.Поможет ли мне moveToThread? Просто он выдает отладочное сообщение с ошибкой.

Должен помочь

Автор: math64 23.4.2013, 07:34
Само создание объекта (конструктор) занимает много времени или или настройка после конструктора?
Объект можно создать в основном потоке, а настроить в отдельном.

Автор: Guinness 23.4.2013, 07:36
xbarmaglot, Вы поток убили, в котором создавался объект? Сам объект "живой"?
moveToThread выдает ошибку типа: "нельзя выполнить данную операцию, т.к. у объекта уже есть parent"?
И как Вы создаете объект в другом потоке? Переопределяете run() у QThread? Или запускаете какой-нибудь асинхронный поток, который по окончании выдает Вам сигнал с параметром в виде созданного объекта?

Автор: xbarmaglot 23.4.2013, 09:47
1. Создание объекта занимает много времени
2. Сам объект создается в run
3. У него нет parent
4. После создания посылается сигнал и поток умирает
5. Сам объект остается жить

Автор: Guinness 23.4.2013, 10:10
Цитата(xbarmaglot @  23.4.2013,  09:47 Найти цитируемый пост)
5. Сам объект остается жить

Точно? Просто Вы создали объект в другом потоке, поток убили, каким образом он должен остаться живым?
Цитата(xbarmaglot @  23.4.2013,  09:47 Найти цитируемый пост)
3. У него нет parent

Тогда другой вопрос:
Цитата(xbarmaglot @  22.4.2013,  20:43 Найти цитируемый пост)
2.Поможет ли мне moveToThread? Просто он выдает отладочное сообщение с ошибкой.

Что за ошибка, приведите, пожалуйста, текст сообщения.
Цитата(xbarmaglot @  23.4.2013,  09:47 Найти цитируемый пост)
1. Создание объекта занимает много времени

Подумайте над вариантом, который предложил math64:
Цитата(math64 @  23.4.2013,  07:34 Найти цитируемый пост)
Объект можно создать в основном потоке, а настроить в отдельном.

Т.е. операцию, занимающую много времени, из конструктора перенести в фукнцию init(), к примеру.

Автор: xbarmaglot 24.4.2013, 10:49
Цитата(Guinness @  23.4.2013,  10:10 Найти цитируемый пост)
Точно? Просто Вы создали объект в другом потоке, поток убили, каким образом он должен остаться живым?

ну и что. parent-а нет, а создан он на куче

Цитата(Guinness @  23.4.2013,  10:10 Найти цитируемый пост)
Что за ошибка, приведите, пожалуйста, текст сообщения.

Код

QObject::moveToThread: Current thread (0x221cc98) is not the object's thread (0x222b590).
Cannot move to target thread (0x221cc98)



Цитата(Guinness @  23.4.2013,  10:10 Найти цитируемый пост)
Т.е. операцию, занимающую много времени, из конструктора перенести в фукнцию init(), к примеру.

не получается. В потоке определяются данные, которые необходимы для создания объекта.

Автор: Guinness 24.4.2013, 11:18
Цитата(xbarmaglot @  24.4.2013,  10:49 Найти цитируемый пост)
QObject::moveToThread: Current thread (0x221cc98) is not the object's thread
(0x222b590).Cannot move to target thread (0x221cc98)


Возможно ошибка кроется в следующем (http://qt-project.org/doc/qt-4.8/qobject.html#moveToThread):
Код

Warning: This function is not thread-safe; the current thread must be same as the current thread affinity. In other words, this function can only
"push" an object[U] from the current thread to another thread, it cannot "pull" an object from any arbitrary thread to the current thread.[/U]

Автор: xbarmaglot 24.4.2013, 11:22
А что делать-то. Сам объект создается в run. Я хочу положить его в main-поток как в документации
Код

myObject->moveToThread(QCoreApplication::instance()->thread());

Автор: Guinness 24.4.2013, 11:28
Я так понимаю, это нужно делать в самом run(). Вы же вроде делаете moveToThread(), в обработчике сигнала, который находится в главном потоке.

Автор: xbarmaglot 24.4.2013, 11:29
Цитата(Guinness @  24.4.2013,  11:28 Найти цитируемый пост)
Я так понимаю, это нужно делать в самом run().

что именно делать в run ? moveToThread?

Автор: Guinness 24.4.2013, 11:30
Цитата(xbarmaglot @  24.4.2013,  11:29 Найти цитируемый пост)
что именно делать в run ? moveToThread?

Да

Автор: xbarmaglot 24.4.2013, 11:36
Guinness, спасибо

Добавлено через 1 минуту и 25 секунд
только конечно криво как-то. что если сигнал подписан на несколько слотов, которые в разных потоках smile

Автор: Guinness 24.4.2013, 11:42
Цитата(xbarmaglot @  24.4.2013,  11:36 Найти цитируемый пост)
только конечно криво как-то. что если сигнал подписан на несколько слотов, которые в разных потоках 

В смысле несколько слотов ожидают один сигнал? Ну вот видимо поэтому так и сделали с moveToThread(). Если каждый поток будет перемещать объект в свой поток, то в итоге будет неопределнность, где же он все таки находится.)

Автор: math64 24.4.2013, 12:51
Цитата(xbarmaglot @  24.4.2013,  10:49 Найти цитируемый пост)
не получается. В потоке определяются данные, которые необходимы для создания объекта. 

Это почти всегда можно сделать. Например, посмотрите, как устроены объекты Qt: есть класс, наследуемый от QObject, и класс XXXPrivate:
Код

class XXX : public QObject
{
Q_OBJECT
piblic:
   XXX() : p(NULL)  {}
   ~XXX() { delete p; }
   void init(YYY* y) { if (p == NULL) p = new XXXPrivate(this, y); }
   void meth() { if (p != NULL) p->meth(); }
signals:
  void signal();
public slots:
  void slot() { if (p != NULL) p->slot(); }
private:
  class  XXXPrivate {
     XXXPrivate(XXX* x, YYY* y) xxx(x) {}
     XXX* xxx;    
     void meth();
     void slot();
  }* p;
}

Таким образом, объект XXX создаётся быстро. Но работать с ним можно будет после вызова init(), который создааст XXXPrivate.
init можно вызвать из другого потока. XXXPrivate не наследуется от QObject и его переность в основной поток не требуется.

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