是否在没有连接的情况下调用槽方法? [英] Invoke slot method without connection?

查看:22
本文介绍了是否在没有连接的情况下调用槽方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我用以下方式实现了一个活动对象。它用于在后台执行长时间的任务。主线程通过向公共槽(即doTask)发送信号来调用任务。以下是一个简化的示例(未经过测试)。

class MyTask : public QObject
{
    Q_OBJECT

public:
    MyTask();
    ~MyTask();

public slots:
    void doTask( int param );

private slots:
    void stated();

signals:
    void taskCompleted( int result );

private:
    QThread m_thread;
};


MyTask::MyTask()
{
   moveToThread(&m_thread);
   connect( &m_thread, SIGNAL(started()), this, SLOT(started()));
   m_thread.start();
}

MyTask::~MyTask()
{
    // Gracefull thread termination (queued in exec loop)
    if( m_thread.isRunning() )
    {
        m_thread.quit();
        m_thread.wait();
    }
}

void MyTask::started()
{
    // initialize live object
}

void MyTask::doTask( int param )
{
    sleep( 10 );
    emit taskCompleted( param*2 );
}

只要doTask()被信号调用,这(应该)就能正常工作。但是,如果主线程直接调用doTask(),那么它将由主线程执行。对于某些任务,我希望由活动对象的线程强制执行,即使是直接调用Slot方法也是如此。

我可以在doTask()前面添加代码,以检查当前线程是否为m_线程,在这种情况下,它将执行该方法。如果不是,我希望doTask()向‘this’发出一个信号,以便doTask()的调用在m_threadexec循环中排队,并由它尽快执行。

我怎么能这样做?

编辑:根据建议的答案,下面是新代码。DoTask方法现在委托活动对象的线程执行,即使直接由主线程调用也是如此。按信号调用仍按预期工作。

class MyTask : public QObject
{
    Q_OBJECT

public:
    explicit MyTask( QObject *parent = 0 );
    ~MyTask();

public slots:
    void doTask( int param );

private slots:
    void doTaskImpl( int param );

signals:
    void taskCompleted( int result );

private:
    QThread m_thread;
};

MyTask::MyTask( QObject *parent) : QObject(parent)
{
   moveToThread(&m_thread);
   m_thread.start();
}

MyTask::~MyTask()
{
    // Gracefull thread termination (queued in exec loop)
    if( m_thread.isRunning() )
    {
        m_thread.quit();
        m_thread.wait();
    }
}

void MyTask::doTask( int param )
{
    QMetaObject::invokeMethod( this, "doTaskImpl", Q_ARG( int, param ) );
}

void MyTask::doTaskImpl( int param )
{
    // Do the live oject's asynchronous task
    sleep( 10 );
    emit taskCompleted( param*2 );
}
这是我所能找到的在单独线程中支持异步方法执行的最简单的实现。一旦线程启动,就会对doTask()方法的调用进行排队和处理。从对象线程调用时,它将立即执行(而不是排队)。

请注意,只有在线程启动时才会发出Started()信号。这意味着在线程启动之前排队的doTask()方法调用将在调用started()方法槽之前执行。这就是我从初始实现中删除它的原因。因此,对象初始化最好在构造函数中执行。

推荐答案

您要调用QMetaObject::invokeMethod来执行此操作。在您的情况下,它看起来像

MyTask *task;
int param;
// ...
// Will automatically change threads, if needed, to execute 
// the equivalent of:
// (void)task->doTask( param );
QMetaObject::invokeMethod( task, "doTask", Q_ARG( int, param ) );

这篇关于是否在没有连接的情况下调用槽方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆