簡體   English   中英

如何將信號從單例線程發送到另一個線程(非單例)

[英]How to send signal from Singleton thread to another thread (Not singleton)

我在創建具有自己線程的Singleton類時遇到了一個問題,該類將信號發送到另一個不是Singleton類的線程。

消費者

class Consumer : public QThread
{
    Q_OBJECT
public:
    explicit Consumer(QObject *parent = 0);
    Consumer(Worker *Worker);
signals:
    void toMessage(const bool& keepCycle);
public slots:
    void getMessage(const QString& str);
private:
    int m_counter;
};

Consumer.cpp

Consumer::Consumer(QObject *parent) :
    QThread(parent)
{
    m_counter = 0;
    connect(Worker::Instance(), SIGNAL(sendMessage(QString)), this, SLOT(getMessage(QString)));
    connect(this, SIGNAL(toMessage(bool)), Worker::Instance(), SLOT(fromMessage(bool)));

}

// Get's message from Singleton thread if counter > 5 sends signal to  terminate cycle in Singleton thread 
void Consumer::getMessage(const QString &str)
{
    m_counter++;
    if(m_counter <= 5) {
        qDebug() << "Got message " << m_counter << ": " << str << "\n";
        return;
    }
    else {
        emit toMessage(false);
    }
}

單例操作如下(懷疑它不是線程安全的 ):

template <class T>
class Singleton
{

public:
    static T* Instance()
    {
        if(!m_Instance) m_Instance = new T;
        assert(m_Instance != NULL);
        return m_Instance;
    }

protected:
    Singleton();
    ~Singleton();
private:
    Singleton(Singleton const&);
    Singleton& operator=(Singleton const&);
    static T* m_Instance;
};

template <class T> T* Singleton<T>::m_Instance = NULL;

工人辛格爾頓班

class Worker : public QThread
{
    Q_OBJECT
public:
    explicit Worker(QObject *parent = 0);
    void run();
signals:
    void sendMessage(const QString& str);
public slots:
    void fromMessage(const bool& keepCycle);
private:
    volatile bool m_keepCycle;
};

typedef Singleton<Worker> Worker;

工作人員

Worker::Worker(QObject *parent) :
    QThread(parent)
{
    m_keepCycle = true;
}

void Worker::run()
{
    while(true) {
        if(m_keepCycle) {
            QString str = "What's up?";
            ElWorker::Instance()->sendMessage(str);
        }
        else {
            qDebug() << "Keep Alive" << false;
            break;
        }
    }
    qDebug() << "Value of keepCycle" << m_keepCycle;

}

void Worker::fromMessage(const bool &keepCycle)
{
    m_keepCycle = keepCycle;
    qDebug() << "\nMessage FROM: " << keepCycle << "\n";
}

main.cpp

Consumer consumer;
ElWorker::Instance()->start();
consumer.start();

您可以幫助我創建線程安全的Singleton並在線程之間發送信號嗎?

首先,強烈建議將worker與它的線程分開:

class Object : public QObject
{
...
public slots:
void onStarted();  // if needed
void onFinished(); // if needed
...
};
...
mObject = QSharedPointer < Object >(new Object);
mThread = new QThread(this);
mObject->moveToThread(mThread);
connect(mThread, SIGNAL(started()), mObject, SLOT(onStarted()));   // if needed
connect(mThread, SIGNAL(finished()), mObject, SLOT(onFinished())); // if needed
mThread->start();

其次,有很多創建單例的方法。 我最喜歡的是:

Object * obj(QObject *parent = 0)
{
    static Object *mObj = new Object(parent);
    return mObj;
}
...
obj(this);        // creating
obj()->doStuff(); // using

現在,關於線程安全。 除非您要發送指針或非常量引用,否則發送信號是線程安全的。 根據您的代碼,您不是。 所以,你應該沒事。

UPDATE

實際上,我沒有在上面得到如何創建線程安全的單例,並且我正在從Worker到Consumer而不是Thread本身發送信號? 遠足

  1. 函數內部的靜態值僅創建和初始化一次,因此,第一次調用obj函數mObj被創建並返回,而每次調用它時, mObj返回先前創建的mObj 另外,我沒有說過,它是線程安全的,我剛才說過-我更喜歡這種方式,然后選擇一個模板,因為:
    1. 它更簡單
    2. 需要更少的代碼
    3. QObject沒有問題
  2. 是的,您應該從工作者類而不是線程一發送信號。 Qt的幫助有一個很好的例子(第一個,而不是第二個): http : //doc.qt.io/qt-5/qthread.html#details QThread唯一應用於-控制線程的流。 在某些情況下,當您需要從QThread派生並重寫QThread::run ,您的情況就不是其中一種。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM