【发布时间】:2016-10-16 14:28:37
【问题描述】:
我有现在的情况:
Worker 是 MainWindow 类中的一个字段,Watchdog 是 Worker 类中的一个字段。
执行如下:
-
Worker被构造class Worker : public QThread { Q_OBJECT public: explicit Worker(); void run(); private: Watchdog *watchdog; bool running = false; signals: void tick(); public slots: void ownerDied(); }; -
Worker的构造函数在堆上构造一个Watchdogclass Watchdog : public QThread { Q_OBJECT public: Watchdog(); void run(); public slots: void tick(); signals: void ownerIsDead(); };-
构造函数在
Watchdog和Worker信号和槽之间执行QObject::connect()connect(this, SIGNAL(tick()), watchdog, SLOT(tick())); connect(watchdog, SIGNAL(ownerIsDead()), this, SLOT(ownerDied())); Worker的主循环以Worker::run()方法开始。Worker启动Watchdog。Watchdog循环启动。如果
Worker在start()调用后5 秒内没有tick(),则Watchdog发出ownerIsDead()信号- Worker 处理
ownerDied()信号,杀死主要的Worker循环 - 如果
Worker确实勾选了Watchdog,他会再睡5 秒 - 整个过程重复
-
问题是,tick() 永远不会到达 Watchdog,ownerIsDead() 信号也不会到达工人,因为它没有打勾。为什么?
这里是原始代码,类名有点不同。
watchdog.h
#ifndef WATCHDOG_H
#define WATCHDOG_H
#define THRESHOLD 1000
#include <QThread>
#include <QObject>
class Watchdog : public QThread
{
Q_OBJECT
public:
Watchdog();
void run();
public slots:
void tick();
void kill();
private:
bool running = false;
bool ticked = false;
signals:
void error();
};
#endif // WATCHDOG_H
watchdog.cpp
#include "watchdog.h"
#include <QDebug>
Watchdog::Watchdog()
{
}
void Watchdog::run()
{
running = true;
qDebug() << "Starting watchdog";
while (running) {
QThread::msleep(THRESHOLD);
qDebug() << "Watchdog tick ... ";
if (!ticked) {
qDebug() << "read() or write() is read";
emit error();
}
}
}
void Watchdog::tick()
{
qDebug() << "Watchdog ticking";
ticked = true;
}
void Watchdog::kill()
{
qDebug() << "Killing watchdog...";
running = false;
}
diskerror.h(又名“工人”)
#ifndef DISKERROR_H
#define DISKERROR_H
#include <QThread>
#include <watchdog.h>
extern "C" {
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <linux/fs.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <time.h>
#include <malloc.h>
}
class DiskError : public QThread
{
Q_OBJECT
public:
explicit DiskError();
void run();
private:
int mismatch(char *a, char *b);
Watchdog *watchdog;
bool running = false;
signals:
void tick();
void killWatchdog();
public slots:
void ownerIsDead();
};
#endif // DISKERROR_H
diskerror.cpp
include "diskerror.h"
#include "watchdog.h"
#include <QDebug>
#define BLKSZ 4096
DiskError::DiskError()
{
watchdog = new Watchdog();
connect(this, SIGNAL(killWatchdog()), watchdog, SLOT(kill()));
connect(this, SIGNAL(tick()), watchdog, SLOT(tick()));
connect(watchdog, SIGNAL(error()), this, SLOT(ownerIsDead()));
}
void DiskError::run()
{
int fd = open("/dev/sdc", O_RDWR | O_SYNC);
if (fd < 0) {
qDebug() << strerror(errno);
}
size_t size;
if (ioctl(fd, BLKGETSIZE64, &size) < 0) {
qDebug() << "IOCTL Error";
return;
}
size_t step = (size / 2500);
size_t done = 0;
int i = 0;
char testing[BLKSZ];
char pattern[BLKSZ];
for (int i = 0; i < BLKSZ; i++) {
pattern[i] = 0xCF;
}
int re, bb, wr;
off_t curr = 0;
watchdog->start();
running = true;
while (running) {
lseek(fd, curr, SEEK_SET);
wr = write(fd, pattern, BLKSZ); /* Write pattern to disk */
lseek(fd, curr, SEEK_SET);
re = read(fd, testing, BLKSZ); /* Read pattern back from disk */
bb = mismatch(pattern, testing);
curr += BLKSZ;
done += BLKSZ;
emit tick();
if ( (re == 0) || (wr < 0) ) {
qDebug() << "Flushing buffers...";
sync();
break;
}
if (done >= step) {
if (bb) {
qDebug() << "[" << i << "] Error occured";
} else {
qDebug() << "[" << i << "] OK";
}
done = 0;
i++;
}
}
emit killWatchdog();
sync();
if (close(fd) < 0) {
qDebug() << "Error closing device";
}
}
int DiskError::mismatch(char *a, char *b)
{
for (int i = 0; i < BLKSZ; i++) {
if ( (*(a+i)) != (*(b+i)) ) return 1;
}
return 0;
}
void DiskError::ownerIsDead()
{
qDebug() << "read() call blocked for more than 5 seconds, device inoperable";
}
我从未在 worker 类中看到调试文本,也没有在 worker 中看到刻度文本。
【问题讨论】:
-
您需要在每个要处理插槽的线程中运行一个事件循环。在您的
Watchdog类中,您不需要使用无限循环覆盖 run 方法。相反,您需要在此线程中创建一个带有计时器的对象。
标签: c++ multithreading qt