在主线程中创建的对象,但不在主线程(QApplication的线程)中创建

时间:2018-08-06 11:27:38

标签: c++ multithreading qt qthread

自2天以来,我一直在尝试解决一个问题:

int main(int argc, char *argv[])
{
    qputenv("QT_IM_MODULE", QByteArray("qtvirtualkeyboard"));
    qputenv("QT_VIRTUALKEYBOARD_STYLE", QByteArray("MacoUV"));

    QApplication app(argc, argv);

    int result;

    MacoUVController * pController = new MacoUVController();

    pController->start();
    std::cout << "MacoUV Controller thread: " << pController->thread() <<std::endl;
    std::cout << "MacoUV Controller thread: " << qApp->instance()->thread() <<std::endl;
    result = app.exec();         
    return result;
}

当我在控制台中显示 pController qApp 线程时,显示了两个不同的线程地址,我不明白为什么,因为所有对象通常都是在主线程中创建的,除非您将它们明确地移动(例如,使用moveToThread)到另一个线程中。

PS:MacoUVController 不能从QThread继承,它只有一个QThread Object成员在代码中的某个位置用于移动另一个对象...

.h of MacoUVController:

class MacoUVController : public MAGenFwk::Controller
{
    Q_OBJECT

public:
    MacoUVController();
    ~MacoUVController();
    bool isStateActive(int);
    void setCurrentCmd(QString cmd);
    QString currentCmd() const;
    QString getTemperatureInfo();
    QString getIlluminationInfo();

signals:
    void sig_serialConnect(QString config);
    void sig_closeMachine();
    void sig_openMachine();
    void sig_sendConfigInfo(QString infos);
    void sig_shutdown();
    void sig_microShutdown();
    void sig_machineOpened(int machineState);
    ...
    ...
private:
    int             a_machineStatus;
    QString         a_currentCmd;
    QThread         a_commThread;
}

MacoUVController ctor

MacoUVController::MacoUVController() : MAGenFwk::Controller()
{    
    a_machineStatus = 0;
    a_isConfigDone  = false;
    a_isConnected   = false;
    a_isShutdownRequested = false;
    a_pModelManager = MAGenFwk::ModelManager::getInstance();
    initModels();

    a_pView = new MainView();

#ifdef SIMULATION
    a_pSimuView = new SimulationView();

    a_pSimuView->show();
#endif

    LabelModel * pLabelModel = dynamic_cast<LabelModel *>(a_pModelManager->getModel("LabelModel"));
    MAGenFwk::FileManagerModel * pFile = new MAGenFwk::FileManagerModel("stylesheet.txt", "");

    connect(a_pView, SIGNAL(sig_dateChanged()), this, SLOT(slt_saveResetDailyInfo()));
    connect(a_pParametersModel, SIGNAL(sig_fileChanged()), this, SLOT(slt_updateParameters()));
    connect(a_pParametersModel, SIGNAL(sig_fileError()), this, SLOT(slt_setFileError()));
    connect(a_pCountersModel, SIGNAL(sig_fileError()), this, SLOT(slt_setFileError()));
    connect(a_pMasksModel, SIGNAL(sig_fileError()), this, SLOT(slt_setFileError()));
    connect(a_pLoginModel, SIGNAL(sig_fileError()), this, SLOT(slt_setFileError()));
    connect(pLabelModel, SIGNAL(sig_fileError()), this, SLOT(slt_setFileError()));
    connect(pFile, SIGNAL(sig_fileError()), this, SLOT(slt_setFileError()));

    a_pParametersModel->load();
    a_pCountersModel->load();
    a_pLoginModel->load();
    a_pMasksModel->load();
    pLabelModel->load();
    pFile->load();

    a_confingInfos = getIlluminationInfo() + getTemperatureInfo();
    a_loginPopupFlag = false;

    a_pAutoLogoutTimer  = new QTimer(this);
    a_shutDownTimer     = nullptr;

    if (a_pDiagManagementModel->isRestricted(EAR_APP))
    {
        a_pView->slt_changeBackground(EAB_ERROR);
        return;
    }

    QFile f(pFile->getFilePath());
    f.open(QIODevice::ReadOnly);
    qApp->setStyleSheet(f.readAll().data());    

    connect(a_pCountersModel, SIGNAL(sig_counterIncremented(QString)), this, SLOT(slt_updateCounter(QString)));    
    connect(a_pView, SIGNAL(sig_usbDriveEvent(QString, bool)), a_pDataManagementModel, SLOT(slt_setUsbDrive(QString, bool)));
    connect(a_pView, SIGNAL(sig_close()), this, SLOT(slt_cleanUp()));
    //std::cout << "Controller thread: " << this->thread() << std::endl;
}

从Controller继承的MacoUVController的启动方法

void Controller::start()
{
    if (a_isStarted == false)
    {
        _createStateMachine();
        _createBehaviors();
        _createTransitions();        

        a_pStateMachine->start();

        EngeneerLog::getInstance();

        _start();

        a_isStarted = true;
    }
}

控制器.h:

class QStateMachine;

namespace MAGenFwk
{
    class Plugin;
    class ModelManager;

    class Controller : public QObject
    {
        Q_OBJECT
    public:
        explicit Controller(QObject *parent = 0);
        ~Controller();

        void start();

    signals:
        void sig_logout();

    private slots:

    protected:
        QStateMachine * a_pStateMachine;
        ModelManager * a_pModelManager;

    private:
        virtual void _createStateMachine() = 0;
        virtual void _createTransitions() = 0;
        virtual void _createBehaviors() = 0;

        virtual void _start();

        bool a_isStarted;
    };

} // end namespace MAGenFwk

#endif

在代码中的某个地方,我通过移动MachineModel使用QThread对象:

a_pMachineModel->moveToThread(&a_commThread);
a_commThread.start();

这是MachineModel的.h:

    class MacoUVMachineModel : public MAGenFwk::MachineModel
{
    Q_OBJECT

public:
    MacoUVMachineModel();
    ~MacoUVMachineModel();

    void manageSpecificMachineStatus(const QString & machineStatus);

    void openMachine();
    void closeMachine();
    void executeMachineOperation(EMachineOp operationType);

    bool isBusy();
    bool isActive(EMachineState machineState);

    bool sendConfigInfo(QString parameters);
    bool startCycle();
    bool stopCycle();
    bool startAutotests();
    bool shutDown();
    bool getVersion(QString & version);    

    MachineData * getMachineData();

signals:
    void sig_machineBusyStateChanged(bool isBusy);
    void sig_machineStateChanged(int stateMask);
    void sig_updateSampleInfos(MachineSample * pSample);
    void sig_machineOperationInProgress(const QString & operation = QString());
    void sig_isConnected(bool serialConnect, bool configDone);
    void sig_cmdExecResult(bool, void*);
    void sig_getConfigInfos();
    void sig_getVersion(QString);
    /**
     * @brief sig_setMachineOp
     * @param mop
     * this signal is created to avoid accessing the GenericPopupModel in MachineModel
     * because then we'll access in two differents thread without any lock, to prevent
     * unpredictable issues, we access the GenericPopupModel in the HMI Thread
     */
    void sig_setMachineOp(EMachineOp mop);

public slots:
    void slt_verifyOperationSuccess();
    void slt_setFailureMessage();
    void slt_serialConnect(QString config);
    void slt_closeMachine();
    void slt_openMachine();
    void slt_startCycle();
    void slt_stopCycle();
    void slt_initAutotests();
    void slt_sendConfigInfo(QString);
    void slt_shutdown();
    void slt_threadFinished();

protected:
    void globalInit();
    void terminate();

private slots:
    void slt_restablishComm();

private:
    void setBusyState(bool isBusy);
    void setMachineState(int stateMask);

    void _initSpecificMachineErrors() {}
    void _initSpecificMachineWarnings() {}

    QString getConfigInfo();
    QString getAgitationInfo();
    QString getIlluminationInfo();
    QString getTemperatureInfo();

    bool a_isBusy;
    int a_lastState;
    int a_machineState;

    MachineData * a_pMachineData;

    QTimer * a_pOperationTimer;

    QString a_operationCmd;

    GenericPopupModel * a_pPopupModel;
    //MAGenFwk::ParametersModel * a_pParametersModel;
    DiagManagementModel * a_pDiagManagementModel;
};

#endif // MACHINEMODEL_H

我使用另一个线程的唯一地方是在Machine对象中移动MachineModel对象,该对象是MacoUVController类的成员。所以对我来说,没有必要让MacoUVController位于不同的线程中,它应该位于主线程中,而只有MachineModel应该位于另一个线程中...也许我弄错了...

Env: -Windows 10 64位(最近升级到1803版本) -基于QT 5.11的Qt Creator 4.7,但我使用的是Qt 5.7,这可能是个问题吗? -编译器:mingw5.3.0 C ++ 32位

有关此问题的任何解释吗?

0 个答案:

没有答案