Какие могут быть подводные камни если сделать глобальный указатель на объект по типу Sensormanager *sensormanager и передать его во второй поток. Определять его видимость через extern в других диалоговых окнах, по типу extern Sensormanager *sensormanager . Цель: иметь возможность сделать связь сигнал - слот из любого диалогового окна или просто сделать обращение к слоту по типу sensormanager->slot со вторым потоком. Или лучше использовать синглет для этих целей?
Недюсь я правильно понял ваши трудности из нескольких вопросов и поэтому рекомендую отделить GUI от логики работы приложения (то есть второго потока, третьего, записей в файлы, чтения из сети и так далее).
Пусть у вас имеется несколько окон (Главное MainWindow в нем Dialog1, Dialog2, первом диалоге поддиалог Dialog11), а также отдельно поток (ваш номер 2) SensorManager (основной поток приложения мы подразумеваем).
Вариант 1. Можно сделать общие интерфейсы сигналов и слотов через посредника ГУИ и отдельного посредника Логики.
Пусть у нас для ГУИ посредником служит главное окно приложения:
class MainWindow ... {
MainWindow() {
connect(&dialog1, SIGNAL(signal1()),
this, SIGNAL(signal1FromDialog1()));
connect(&dialog1, SIGNAL(signal1Dialog11()),
this, SIGNAL(signal1FromDialog11()));
...
}
signals:
void signal1FromDialog1();
void signal2FromDialog1();
void signal3FromDialog1(<какие-то аргументы>);
void signal1FromDialog11(); // ! От Dialog11
void signal1FromDialog2();
void signal2FromDialog2(<какие-то аргументы>);
и так далее
public slots:
// Для слотов диалога 1
void callSlot1Dialog1(<аргуенты и без них>) {
dialog1.callSlot1(...);
}
void callSlot2Dialog1(<аргуенты и без них>) { ... }
// Для слотов поддиалога 1 диалога 1, то есть для Dialog11
void callSlot3Dialog11(<аргуенты и без них>) {
dialog1.callDialog11Method1(...);
}
// Для слотов диалога 2
void callSlot1Dialog2(<аргуенты и без них>) {
dialog2.callSlot1(...)
}
void callSlot2Dialog2(<аргуенты и без них>) { ... }
и так далее
private:
Dialog1 dialog1;
Dialog2 dialog2;
...
}
Тоже самое для логики:
class Logic : public QObject {
Q_OBJECT
signals:
void someSignalFromThread(<Здесь могли бы быть ваши аргументы>);
public slots:
void callSlotForThread() {
sensorManager->someSlot();
}
private:
SensorManager* sensorManager;
}
Далее мы все это хозяйство сшиваем/соединяем:
void main() {
MainWindow window;
Logic logic;
QObject::connect(&window, SIGNAL(signal1FromDialog1()),
&logic, SLOT(callSlotForThread()));
еще коннект за маму,
еще коннект за папу,
Коннект из логики в окно
QObject::connect(&logic, SIGNAL(signal1SensorManager()),
&window, SLOT(callSlotForDialog1()));
еще коннект из логики, (может быть вы добавите третий поток и т.д.)
...
return a.exec();
}
Вариант 2. Мы не делаем общий интерфейс слотов, сигналов, а предоставляем сами объекты окон, диалогов, потоков и тому подобное. Тогда main будет выглядеть так:
void main() {
MainWindow window;
Logic logic;
...
QObject::connect(&window.dialog1(), SIGNAL(signal1FromDialog1()),
&logic, SLOT(callSlot1ForThread()));
QObject::connect(&window.dialog1().dialog11(), SIGNAL(signal1FromDialog11()),
&logic, SLOT(callSlot2ForThread()));
ИЛИ!
QObject::connect(&window.dialog1(), SIGNAL(signal1FromDialog1()),
logic.sensorManager(), SLOT(callSlot1()));
...
return a.exec();
}
Вариант 3. Отдельные окна и диалоги и поддиалоги, и отдельное их связывание друг с другом, но для средних (больше 4-5 объектов) и больших приложений это плохая идея.
Надеюсь идея ясна
Какие могут быть подводные камни если сделать глобальный указатель на объект по типу Sensormanager *sensormanager и передать его во второй поток
Подводные камни? Конфликт между потоками при доступе к глобальному объекту. Если два или более потока будут осуществлять доступ к одному и тому же участку памяти, и один из потоков будет вызывать изменение этой памяти, то будет существовать состояние гонки и, как следствие, неопределённое поведение, за исключением случаев, когда:
обе операции являются атомарными, или
выполнение операций синхронизировано друг с другом (для этих целей подходит std::mutex
).
Это будет верно для любого объекта (не обязательно глобального), к которому будут иметь доступ два или более потока, так как в C++ любой поток всегда может обратиться к любому объекту, существующему в программе, если адрес этого объекта был каким-либо способом передан этому потоку.
Обеспечьте потоко-безопасность путём добавления мьютексов во все методы чтения/записи объекта.
В этом примере доступ к Object::value_
защищён std::lock_guard<std::mutex>
, и два или более потока могут безопасно одновременно вызвать методы set
и get
.
class Object
{
public:
void set(const std::string & content);
std::string get();
private:
std::string value_;
std::mutex mtx_;
};
void Object::set(const std::string & content)
{
std::lock_guard<std::mutex> lock(mtx_);
value_ = content;
}
std::string Object::get()
{
std::lock_guard<std::mutex> lock(mtx_);
return value_;
}
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Два скрипта взаимодействуют друг с другом: один написан на React, другой на jQueryВ React-компоненте есть textarea и есть событие onChange, которое изменяет...
Есть сайт генератор паролейТам при нажатии на кнопку идет плавный скролл
Есть текст в richTextBox1Как проверить, является ли выделенная область жирным текстом?
Пытаюсь использовать Invoke для того, чтобы использовать winform-контролы в другом потокеИ один из аргументов у меня по задумке должен быть ref