有人可以告诉我为什么这个qt代码在定义ASYNC_TIMERS时不会调用Callback(即从pthread调用m_timer.start但是插槽永远不会运行)。显然它是从一个pthread调用,因为当ASYNC_TIMERS没有定义但是我想知道如何从pthread修复它时它工作。我已经尝试了很多在网上找到的东西,包括moveToThread(),调用运行调用exec()的线程,但我对这个问题没有运气?
干杯
multitimer.h:
#pragma once
#ifndef MULTI_TIMER_H
#define MULTI_TIMER_H
#include <QThread>
#include <QTimer>
#include <QMutex>
#include <QMap>
#include <QMetaType>
#include <cassert>
class MultiTimer : public QThread
{
Q_OBJECT
public:
typedef void (*multiTimerCallback)(quint32 p_id);
private:
QTimer m_timer;
QMutex m_mutex;
quint32 m_id;
multiTimerCallback m_callback;
void KillTimer(void);
public:
// only TimerFactory is allowed to instantiate MultiTimer
MultiTimer(quint32 p_id, multiTimerCallback p_callback);
~MultiTimer();
enum TTimerType
{
TT_SingleShot, ///< Timer fires only once
TT_Repetitive ///< Timer keeps firing repeatedly until stopped with KillTimer()
};
void SetTimer(quint32 p_delayInMilliseconds, MultiTimer::TTimerType timerType);
private slots:
void Update(void);
};
#endif
timer.cpp:
#include <QtCore/QCoreApplication>
#include "multitimer.h"
#include <stdio.h>
//--------------------------------------------------------------------------------------------------
void MultiTimer::SetTimer(quint32 p_delayInMilliseconds, MultiTimer::TTimerType timerType)
{
QMutexLocker locker(&m_mutex);
m_timer.setSingleShot(TT_SingleShot == timerType ? true : false);
m_timer.start(p_delayInMilliseconds);
//QTimer::singleShot(p_delayInMilliseconds, this,SLOT(Update()));
}
void MultiTimer::KillTimer(void)
{
QMutexLocker locker(&m_mutex);
m_timer.stop();
}
void MultiTimer::Update(void)
{
QMutexLocker locker(&m_mutex);
if (NULL != m_callback)
m_callback(m_id);
}
MultiTimer::MultiTimer(quint32 p_id, multiTimerCallback p_callback)
: m_id(p_id)
, m_callback(p_callback)
{
bool isConnected = true;
isConnected &= this->connect(&this->m_timer, SIGNAL(timeout()), this, SLOT(Update()), Qt::QueuedConnection);
assert(isConnected);
//this->start();
}
MultiTimer::~MultiTimer()
{
KillTimer();
wait();
}
//--------------------------------------------------------------------------------------------------
#define ASYNC_TIMERS
#define GLOBAL_TIMERS
void Callback(quint32 p_id)
{
printf("Got timered by timer %d.\n", p_id);
}
MultiTimer *mt;
void StartTimers(void)
{
#ifndef GLOBAL_TIMERS
mt = new MultiTimer(1, Callback);
#endif
mt->SetTimer(1000, MultiTimer::TT_SingleShot);
}
#ifdef ASYNC_TIMERS
pthread_t AsyncTaskThread;
void *ProcessAsyncTasks(void */*ptr*/)
{
StartTimers();
return NULL;
}
#endif
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
#ifdef GLOBAL_TIMERS
mt = new MultiTimer(1, Callback);
#endif
#ifdef ASYNC_TIMERS
pthread_create(&AsyncTaskThread, NULL, &ProcessAsyncTasks, NULL);
#else
StartTimers();
#endif
return a.exec();
}
答案 0 :(得分:3)
我认为Threads and QObjects有答案:您不能在与创建它的位置不同的线程中使用事件驱动的对象。
在您的代码中,如果启用了GLOBAL_TIMERS
,您将在主代码中创建MultiTimer
线程,但在另一个中调用m_timer.start()
。
引用文档:
事件驱动对象只能在单个线程中使用。具体而言,这适用于计时器机制和网络模块。例如,您无法在不是对象线程的线程中启动计时器或连接套接字。
所以不要这样做。 (并使用QThread,而你正在使用它。)
答案 1 :(得分:1)
您需要一个QEventLoop来处理新线程中的信号/插槽内容。
QTimer需要这些工作。
void *ProcessAsyncTasks(void */*ptr*/)
{
QEventLoop loop;
StartTimers();
loop.exec();
return NULL;
}
为什么不使用QThread?
答案 2 :(得分:0)
没有人也试图解决这个问题,我想我想出来了,如果我将m_timer和multitimer对象移回主qt线程并“正确”发出计时器启动信号,这一切似乎都有效(见下文) )。
可能我仍然可以在qthread中进行exec调用以接管pthread并将multitimer和m_timer移动到那个,但这种方式现在可以工作了,我得到了“得到了定时器%d。\ n”的时间。即使在pthread根据需要死后也按时输出。:
感谢所有人提供的意见,如果有更好的方法可以做到这一点,或者我忽略了一个大错误,那将会很高兴知道吗?干杯
multitimer.h:
/**
@file multitimer.h
@brief Partial implementation of Windows-like SetTimer()/KillTimer() for Qt.
*/
#pragma once
#ifndef MULTI_TIMER_H
#define MULTI_TIMER_H
#include <QThread>
#include <QTimer>
#include <QMutex>
#include <QMap>
#include <QMetaType>
#include <cassert>
class MultiTimer : public QThread
{
Q_OBJECT
public:
typedef void (*multiTimerCallback)(quint32 p_id);
private:
QTimer m_timer;
QMutex m_mutex;
quint32 m_id;
multiTimerCallback m_callback;
void KillTimer(void);
public:
// only TimerFactory is allowed to instantiate MultiTimer
MultiTimer(quint32 p_id, multiTimerCallback p_callback);
~MultiTimer();
enum TTimerType
{
TT_SingleShot, ///< Timer fires only once
TT_Repetitive ///< Timer keeps firing repeatedly until stopped with KillTimer()
};
void SetTimer(quint32 p_delayInMilliseconds, MultiTimer::TTimerType timerType);
private slots:
void Update(void);
signals:
void start_sig(int);
};
#endif
timer.cpp:
#include <QtCore/QCoreApplication>
#include "multitimer.h"
#include <stdio.h>
//--------------------------------------------------------------------------------------------------
void MultiTimer::SetTimer(quint32 p_delayInMilliseconds, MultiTimer::TTimerType timerType)
{
QMutexLocker locker(&m_mutex);
m_timer.setSingleShot(TT_SingleShot == timerType ? true : false);
connect(this, SIGNAL(start_sig(int)), &m_timer, SLOT(start(int)), Qt::QueuedConnection);
//m_timer.start(p_delayInMilliseconds);
emit start_sig(p_delayInMilliseconds);
disconnect(this, SIGNAL(start_sig(int)), &m_timer, SLOT(start(int)));
}
void MultiTimer::KillTimer(void)
{
QMutexLocker locker(&m_mutex);
m_timer.stop();
}
void MultiTimer::Update(void)
{
QMutexLocker locker(&m_mutex);
if (NULL != m_callback)
m_callback(m_id);
}
MultiTimer::MultiTimer(quint32 p_id, multiTimerCallback p_callback)
: m_id(p_id)
, m_callback(p_callback)
{
bool isConnected = true;
isConnected &= this->connect(&this->m_timer, SIGNAL(timeout()), this, SLOT(Update()), Qt::QueuedConnection);
assert(isConnected);
//this->start();
moveToThread(qApp->thread());
m_timer.moveToThread(qApp->thread());
}
MultiTimer::~MultiTimer()
{
KillTimer();
wait();
}
//--------------------------------------------------------------------------------------------------
#define ASYNC_TIMERS
#define xGLOBAL_TIMERS
void Callback(quint32 p_id)
{
printf("Got timered by timer %d.\n", p_id);
}
MultiTimer *mt;
void StartTimers(void)
{
#ifndef GLOBAL_TIMERS
mt = new MultiTimer(1, Callback);
#endif
mt->SetTimer(2000, MultiTimer::TT_SingleShot);
}
#ifdef ASYNC_TIMERS
pthread_t AsyncTaskThread;
void *ProcessAsyncTasks(void */*ptr*/)
{
StartTimers();
return NULL;
}
#endif
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
#ifdef GLOBAL_TIMERS
mt = new MultiTimer(1, Callback);
#endif
#ifdef ASYNC_TIMERS
pthread_create(&AsyncTaskThread, NULL, &ProcessAsyncTasks, NULL);
#else
StartTimers();
#endif
return a.exec();
}