LINUX.ORG.RU

QThread: зачем нужен moveToThread?

 ,


0

3

Потребовалось мне сделать выполнение в отдельном потоке, и начал разбирать что к чему. Может ли мне кто объяснить, зачем нужен moveToThread? Что за родственность (affinity) меняется при его выполнении? Ведь если нить создается в текущем процессе, то память у нее общая и доступная в текущим процессе. Или без этого метод объекта, который туда не перемещен не будет выполняться в той нити? И одновременный доступ к свойствам все равно нужно контролировать через мютексы. На что влияет это перемещение?

QThread* th = new QThread;
MyObject* obj = new MyObject;
obj->moveToThread(th);
obj->doSomeThing();

такая вещь по прежнему может выполняться в текущей нити, несмотря на то что я сказал объекту переместиться в другую нить.

Если вам нужен низкоуровневый контроль - смотрите в сторону QThread::run. moveToThread для другого.

RazrFalcon ★★★★★
()

сигналы/слоты и события по разному работают с объектами их одного потока и с объектами из разных потоков. Дабы сообщить Qt ,что события для данного объекта будут выполняться на этом потоке, используется тот самый moveToThread

maxis11
()
Ответ на: комментарий от maxis11

сигналы/слоты и события по разному работают с объектами их одного потока и с объектами из разных потоков. Дабы сообщить Qt ,что события для данного объекта будут выполняться на этом потоке, используется тот самый moveToThread

Правильно ли я понял, что всякий слот у перемещенного объекта будет выполняться в потоке, в который был перемещен объект, независимо от того, из какого потока произошел emit?

Тогда получается, что привязывать запуск метода к thread->start() совсем не нужно. thread->start() запускает цикл обработки событий, а желаемый метод можно позже запустить через систему сигналов/слотов.

victor79
() автор топика
Ответ на: комментарий от victor79

Да. Но типа это не по стандарту придуманному культеписателями. Я тебе советую использовать то, что они предлагают в примерах, т.е. мувтотред, иначе может возникнуть сегментейшн фаулт какойнить. Ну есть у них рамки, чтобы не гуглить пару недель — просто следуй тому что предлагают.

deep-purple ★★★★★
()
Ответ на: комментарий от victor79

Правильно ли я понял, что всякий слот у перемещенного объекта будет выполняться в потоке, в который был перемещен объект, независимо от того, из какого потока произошел emit?

Не совсем так.

Когда делается connect(), то у него указывается тип - Direct или Queued. Если Direct, то слот выполняется в том же потоке, что и сигнал (обычный вызов функции). Если Queued - то в том потоке, к которому «привязан» объект.

Если тип соденинения не указан (или указан AutoConnection), то - тадам - происходит проверка, к одному ли потоку привязаны соединяемые объекты или к разным, в первом случае работает как Direct, во втором как Queued

annulen ★★★★★
()

Потребовалось мне сделать выполнение в отдельном потоке, и начал разбирать что к чему. Может ли мне кто объяснить, зачем нужен moveToThread?

Для этого и нужен.

Что за родственность (affinity) меняется при его выполнении?

Вырвано из контекста, но очевидно речь про древовидную структкру QObject::QObject(*parent)

Ведь если нить создается в текущем процессе, то память у нее общая и доступная в текущим процессе.

У потоков разный eventloop, это очень важная штука и её нужно понимать.

такая вещь по прежнему может выполняться в текущей нити, несмотря на то что я сказал объекту переместиться в другую нить.

Ты напрямую дергаешь код вызывая метод объекта. А вот если дергать через сигнал-слот, система eventloop'ов обеспечит выполнение вызванного слота в отдельном потоке. И даже если в уже существующем коде резко воткнуть moveToThread, при условии что фреймворк использовался изначально правильно, код будет работать без прочих изменений. Потому выше и говорил: нужно понимать eventloop. Eventloop и сигнал-слот в Qt - краеугольный камень.

erfea ★★★★★
()

obj->doSomeThing();

Выполнит код метода doSomeThing() в контексте вызывающего треда

QMetaObject::invokeMethod(obj,"doSomeThing",Qt::QueuedConnection)

или

connect(this,&Parent::someSignal,obj,&MyObject::doSomeThing,Qt::QueuedConnection);
emit someSignal();

Выполнит код метода doSomeThing() в контексте того треда с которым «связан» объект obj. moveToThread - метод для смены привязки объекта к треду. По умолчанию объект привязан к тому треду в котором был выполнен его конструктор.

anonymous
()
Ответ на: комментарий от victor79

Тогда получается, что привязывать запуск метода к thread->start() совсем не нужно. thread->start() запускает цикл обработки событий, а желаемый метод можно позже запустить через систему сигналов/слотов.

QThread::start() отличается от QThread::exec(), т.к. просто запускает пользовательскую виртуальную функцию run(). В результате thread не будет иметь собственного цикла обработки событий, а значит не будут вызываться функции-слоты в контексте этого потока.

m0rph ★★★★★
()
Последнее исправление: m0rph (всего исправлений: 1)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.