После прочтения документации я наткнулся на это:
Дочерний элемент QObject
всегда должен создаваться в потоке, в котором был создан родительский элемент.Это подразумевает, среди прочего, что вы никогда не должны передавать объект QThread
(this) как родительский объект для объекта, созданного в потоке (поскольку сам объект QThread
был создан в другом потоке).
Я не совсем уверен, что это значит, поэтому я сделал несколько примеров и подумал, где это применимо.
A.
class MyThread : public QThread {
MyThread(QObject *parent = 0) : QThread(parent) {
QNetworkAccessManager *test = new QNetworkAccessManager (this);
// here I assume that this child(test) will have the main thread (creator of MyThread)
// as it's parent and it will go horrible wrong.
}
....
}
B.
class MyThread : public QThread {
QNetworkAccessManager *test;
MyThread(QObject *parent = 0) : QThread(parent) {}
void run {
test = new QNetworkAccessManager(this);
// will the main thread be the parent here aswell?
// if I remove "this" this will work since its created in the thread (not the main thread)
}
....
}
Окей, а как насчет этого?
Обратите внимание, что эти объекты будут созданы и запущены следующим образом:
MyThread *fakeThread = new MyThread; // should I or should I not pass "this" as a parent here?
QThread realThread;
fakeThread->moveToThread(&realThread);
realThread.start();
QMetaObject::invokeMethod(fakeThread, "start", Qt::QueuedConnection);
C.
class MyThread : public QObject {
MyThread(QObject *parent = 0) : QObject(parent) {
QNetworkAccessManager *test = new QNetworkAccessManager(this);
// I assume this constructor still will be create the the QNAM as a child to
// the main thread and it will not work
}
void start {
....
}
}
D.
class MyThread : public QObject {
QNetworkAccessManager *test;
MyThread(QObject *parent = 0) : QObject(parent) {}
void start {
test = new QNetworkAccessManager(this);
// What about now?
}
....
}
Я действительно хочу реализовать опцию D, чтобы у меня было множество объектов, которые можно легко удалить.Например, если я хочу прочитать большое количество файлов, и я хочу, чтобы все они были перераспределены, когда поток умирает.
Кроме того, в чем главное отличие производной версии QThread
от той, в которой вы перемещаете QObject
в поток?В документации всегда указывается, что нужно делать, а что нет при работе с Qthread
, но я немного не уверен в этом.
Моя самая большая проблема сейчас в том, что у меня есть класс, производный от QObject
, который будет перемещен в поток.В этом объекте я создаю другой объект.Этот объект содержит QNetworkAccessManager
и QFile
.Куда бы я передал «это» как родитель, или я вообще не должен этого делать, находясь в потоке?Пожалуйста, объясни.
В данный момент в куче создается объект (назовем его RestHandler
), принадлежащий объекту (uploader
, который является потоком).Это потому, что большинство функций использует его, и если он создан в заголовочном файле в стеке, его родитель будет основным потоком.В RestHandler
a QNetworkAccessManager
будет создан в стеке.
Редактировать:
После прочтения ответов я попытался создать в стеке restHandler
и QNetworkAccessManager
, а затем переместить их.Вывод был следующим:
Resthandeler
конструктор: restHandler
создан в потоке QThread
(0x22d5e8) с accessManager в потоке QThread
(0x22d5e8) текущее местоположение QThread (0x22d5e8)
Затем, когда я пытаюсь переместить resthandler
, я получаю следующее предупреждение:
QObject::moveToThread: Current thread (0x1fbf0e0) is not the object's thread (0x22d5e8).
Cannot move to target thread (0x1fbf0e0)
QObject: Cannot create children for a parent that is in a different thread.
(Parent is QNetworkAccessManager(0x42a477c), parent's thread is QThread(0x22d5e8), current thread is QThread(0x4196f98)
Я думаю, что нет способа решить эту проблему?Кажется, что программа работает, и слоты вызываются в нужных потоках, но, похоже, вопрос времени, прежде чем она выйдет из строя.