Комментарии 23
Чтобы те, кому интересно, могли следить за изменениями в статья, я в этом комментарии буду описывать все изменения в тексте.
Комментарий можно редактировать только первые три минуты после его публикации, так что не выйдет :)
Изменения в тексте принято помечать UPD прямо в тексте, также к вашим услугам тег <s>который позволяет делать так
Изменения в тексте принято помечать UPD прямо в тексте, также к вашим услугам тег <s>
Это да, но: допустим, мне понравилась статья. По ней пошла дискуссия, в которой принимает участие и автор тоже. И вот, он вносит правки, а мне они также интересны. Мне было бы очень удобно, если бы он в одном месте перечислял бы все свои правки — иначе я должен периодически просматривать весь текст в поисках оных
Чтобы ничего больше не потерялось советую использовать плагин к браузеру Lazarus.
addons.mozilla.org/en-US/firefox/addon/lazarus-form-recovery/
chrome.google.com/webstore/detail/lazarus-form-recovery/loljledaigphbcpfhfmgopdkppkifgno?hl=en
addons.mozilla.org/en-US/firefox/addon/lazarus-form-recovery/
chrome.google.com/webstore/detail/lazarus-form-recovery/loljledaigphbcpfhfmgopdkppkifgno?hl=en
А зачем вообще нужна такая сущность, как ThreadedObject? Я считаю, потоки должны быть отделены от объектов. Single responsibility же.
Также, как и сборка мусора в памяти: ThreadedObject гарантирует удаление объекта. А может и не гарантировать, если так удобно клиенту.
Как правильно использовать QThread
И все. Не усложняйте шаблонами там, где это не требуется.
class Worker : public QObject {
Q_OBJECT
public:
Worker();
virtual ~Worker();
public slots:
void process();
signals:
void finished();
void error(QString err);
private:
// add your variables here
};
// --- CONSTRUCTOR ---
Worker::Worker() {
// you could copy data from constructor arguments to internal variables here.
}
// --- DECONSTRUCTOR ---
Worker::~Worker() {
// free resources
}
// --- PROCESS ---
// Start processing data.
void Worker::process() {
// allocate resources using new here
qDebug("Hello World!");
emit finished();
}
QThread* thread = new QThread;
Worker* worker = new Worker();
worker->moveToThread(thread);
connect(worker, SIGNAL(error(QString)), this, SLOT(errorString(QString)));
connect(thread, SIGNAL(started()), worker, SLOT(process()));
connect(worker, SIGNAL(finished()), thread, SLOT(quit()));
connect(worker, SIGNAL(finished()), worker, SLOT(deleteLater()));
connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
thread->start();
И все. Не усложняйте шаблонами там, где это не требуется.
Нет. Это неправильный метод. Если вам нужно выполнить единичную работу, то можно использовать пул потоков (его наконец-то починили) + runnable, или Qt concurrent, или переопределить метод run у потока.
Если вы создаете некоторый сервис, который будет работать в отдельном потоке, получая сигналы от клиентов, то останавливать сам себя он не сможет, это должен делать контроллер сервиса.
Если вы создаете некоторый сервис, который будет работать в отдельном потоке, получая сигналы от клиентов, то останавливать сам себя он не сможет, это должен делать контроллер сервиса.
Вот как раз переопределять метод run у QThread — это и есть неправильный способ, который, тем не менее, получил самое широкое распространение, и именно для исправления этой ситуации и была написана статья по ссылке:
This should immediately show why the recommended way of using QThreads in the documentation, namely to sub-class it and implement your own run() function, is very wrong.
Не нужно путать 2 варианта использования потока, которые я описал выше. Для второго варианта, это действительно неправильный способ, а для первого — ок.
Я понимаю, что теперь все прочитали Qt threads you're doing it wrong и носятся вокруг него, но есть и альтернативные мнения.
Я понимаю, что теперь все прочитали Qt threads you're doing it wrong и носятся вокруг него, но есть и альтернативные мнения.
>Не нужно путать 2 варианта использования потока, которые я описал выше
В первую очередь не нужно путать «использование потоков» и «использование QThread». Я говорю и изначально говорил о последнем и только о последнем, поэтому вариантов с QThreadPool или QtConcurrent даже не касался.
Что касается «альтернативного мнения» — вы прочитайте внимательно статью-то. Она кагбэ слегка ортогональна тому, что написано по моей ссылке, там совсем другой подход рассматривается и оспаривается.
В первую очередь не нужно путать «использование потоков» и «использование QThread». Я говорю и изначально говорил о последнем и только о последнем, поэтому вариантов с QThreadPool или QtConcurrent даже не касался.
Что касается «альтернативного мнения» — вы прочитайте внимательно статью-то. Она кагбэ слегка ортогональна тому, что написано по моей ссылке, там совсем другой подход рассматривается и оспаривается.
ну обычно, если речь не идет о лабораторной работе, нужно все-таки решить задачу, а не использовать feature %featurename%, так что первое возражение не принимается.
Что касается второго, то весь шум пошел от статьи QThread: you're doing it wrong в блоге Qt. А то что я привел — собственно реакция на эту статью.
Что касается второго, то весь шум пошел от статьи QThread: you're doing it wrong в блоге Qt. А то что я привел — собственно реакция на эту статью.
Я извиняюсь, но это не «возражение», это изначальная постановка задачи: «если уж мы используем QThread, то делать это нужно следующим образом». По крайней мере я подразумевал именно такую постановку задачи, и довольно четко это указал. И решение в статье, как вы сами видите, использует именно QThread.
Так что не вы «не принимаете мое возражение», это я не принимаю вашу измененную задачу (подразумевающую множество решений в зависимости от неизвестных дополнительных условий).
>Что касается второго, то весь шум пошел от статьи QThread: you're doing it wrong в блоге Qt. А то что я привел — собственно реакция на эту статью.
То есть вы привели «ответ на статью X» в качестве ответа на статью Y, которая довольно сильно отличается от статьи X? Вам не кажется, что тут что-то не так?
Так что не вы «не принимаете мое возражение», это я не принимаю вашу измененную задачу (подразумевающую множество решений в зависимости от неизвестных дополнительных условий).
>Что касается второго, то весь шум пошел от статьи QThread: you're doing it wrong в блоге Qt. А то что я привел — собственно реакция на эту статью.
То есть вы привели «ответ на статью X» в качестве ответа на статью Y, которая довольно сильно отличается от статьи X? Вам не кажется, что тут что-то не так?
ок, вы можете делать, как хотите, а я буду делать так, как эффективнее всего.
та ссылка, которая у вас приведена — собственно разъяснение в деталях статьи QThread: you're doing it wrong.
та ссылка, которая у вас приведена — собственно разъяснение в деталях статьи QThread: you're doing it wrong.
Я раньше думал, что так оно и вправду лучше. Но сравните Вашу и мою реализацию: у Вас объект создается ДО создания потока — и поэтому потом необходимо его moveToThread. У меня же он изначально создается в новом потоке. Я думаю, что по-моему эффективней.
Это, в обшем, не важно. Потому что если скорость создания потока становится важна, то у вас есть более серьезные проблемы.
Уж не знаю, сколько микросекунд вы выиграете на перемещении объекта в поток, но за приведенный мной вариант есть как миниму 2 аргумента:
1) Он более поддерживаемый. Просто сравните объем кода для прочтения и понимания другим человеком.
2) Ваш шаблон (как и все шаблоны) будет генерировать отдельный класс на каждый класс-параметр, и при малейшем изменении в вашем классе будет происходить перекомпиляция всего зависимого кода (я даже не говорю о размере бинарника и занимаемой памяти, т.к. это не всегда настолько критично).
1) Он более поддерживаемый. Просто сравните объем кода для прочтения и понимания другим человеком.
2) Ваш шаблон (как и все шаблоны) будет генерировать отдельный класс на каждый класс-параметр, и при малейшем изменении в вашем классе будет происходить перекомпиляция всего зависимого кода (я даже не говорю о размере бинарника и занимаемой памяти, т.к. это не всегда настолько критично).
Не усложняйте шаблонами там, где это не требуется
Как по мне, то в данном случае это очень в тему — получаем очень удобное решение для многоразового использования.
А чем вам приведенное мной решение не «многоразовое»? Затолкайте Worker в библиотеку, добавьте ему виртуальный protected метод, в котором будет сама логика, спрячьте кусок кода с созданием QThread и соединением сигналов в отдельный «запускающий» метод — и на стороне клиентского кода использование будет заключаться в наследовании от Worker (чисто для переопределения метода с логикой — минимум дополнительного кода), создании его экземпляра и вызове запускающего метода.
не туда ответил, прошу прощения.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Qt: шаблон для корректной работы с потоками — более качественная реализация