简体   繁体   English

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

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

I'm facing a problem while creating a Singleton class with it's own thread that sends signal to another thread which is not a singleton class. 我在创建具有自己线程的Singleton类时遇到了一个问题,该类将信号发送到另一个不是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.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 is done as follows (suspect it's Not Thread-safe ): 单例操作如下(怀疑它不是线程安全的 ):

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;

And Worker Singleton class 工人辛格尔顿班

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

The main.cpp main.cpp

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

Can you help me to create thread-safe Singleton and to send signals between threads? 您可以帮助我创建线程安全的Singleton并在线程之间发送信号吗?

First of all, it is highly recommended to separate worker from it's thread: 首先,强烈建议将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();

Second of all, there are a lot of ways of creating a singleton. 其次,有很多创建单例的方法。 My favourite is this: 我最喜欢的是:

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

Now, about thread-safety. 现在,关于线程安全。 Sending signals is thread-safe, unless you're sending pointers or non-constant references. 除非您要发送指针或非常量引用,否则发送信号是线程安全的。 Which, according to your code, you are not. 根据您的代码,您不是。 So, you should be fine. 所以,你应该没事。

UPDATE UPDATE

Actually, I didn't get how created thread-safe singleton above and I'm sending a signal from Worker TO Consumer Not a Thread itself? 实际上,我没有在上面得到如何创建线程安全的单例,并且我正在从Worker到Consumer而不是Thread本身发送信号? hiken 远足

  1. Static values inside of function are created and initialized only once, so the first time you call obj function mObj is created and returned and each other time you call it, previously created mObj is returned. 函数内部的静态值仅创建和初始化一次,因此,第一次调用obj函数mObj被创建并返回,而每次调用它时, mObj返回先前创建的mObj Also, I didn't say, it's thread-safe, all I said - I like this way better, then template one, because: 另外,我没有说过,它是线程安全的,我刚才说过-我更喜欢这种方式,然后选择一个模板,因为:
    1. it is simplier 它更简单
    2. requires less code 需要更少的代码
    3. works with QObject without problems QObject没有问题
  2. Yes, you should send signals from worker class, not thread one. 是的,您应该从工作者类而不是线程一发送信号。 Qt's help has a good example (the first one, not the second one): http://doc.qt.io/qt-5/qthread.html#details . Qt的帮助有一个很好的例子(第一个,而不是第二个): http : //doc.qt.io/qt-5/qthread.html#details The only thing QThread should be used for - is controlling thread's flow. QThread唯一应用于-控制线程的流。 There are some situations, when you need to derive from QThread and rewrite QThread::run , but your case isn't one of them. 在某些情况下,当您需要从QThread派生并重写QThread::run ,您的情况就不是其中一种。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM