如何从Singleton线程发送信号到另一个线程(非单例)

时间:2015-05-12 07:30:35

标签: multithreading qt thread-safety

我在使用自己的线程创建Singleton类时遇到问题,该线程将信号发送到另一个不是单例类的线程。

Consumer.h

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);
    }
}

Singleton完成如下(怀疑它是非线程安全):

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.cpp

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并在线程之间发送信号吗?

1 个答案:

答案 0 :(得分:0)

首先,强烈建议将工作人员与其分开:

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

现在,关于线程安全。发送信号是线程安全的,除非您发送指针或非常量引用。根据你的代码,你不是。所以,你应该没事。

<强>更新

  

实际上,我没有得到上面创建的线程安全单例的方法,而且我还没有   从工人发送信号到消费者不是线程本身? - hiken

  1. 函数内部的静态值只创建并初始化一次,因此第一次调用obj函数mObj时会创建并返回,并且每隔一次调用它,之前创建的{{1}返回。另外,我没有说,它是线程安全的,我所说的 - 我更喜欢这种方式,然后是模板一,因为:
    1. 更简单
    2. 需要更少的代码
    3. mObj合作无问题
  2. 是的,您应该从工人类发送信号,而不是线程1。 Qt的帮助有一个很好的例子(第一个,而不是第二个):http://doc.qt.io/qt-5/qthread.html#details。唯一应该用QObject的东西 - 是控制线程的流程。在某些情况下,您需要从QThread派生并重写QThread,但您的情况不是其中之一。