mirror of
https://github.com/jaredtao/TaoQuick.git
synced 2025-01-31 21:22:58 +08:00
130 lines
4.1 KiB
C
130 lines
4.1 KiB
C
|
#pragma once
|
|||
|
#include "taocommonglobal.h"
|
|||
|
#include "threadcommon.h"
|
|||
|
#include <QMap>
|
|||
|
#include <QThread>
|
|||
|
namespace TaoCommon
|
|||
|
{
|
|||
|
// 对Qt Worker-Controller 线程模型的简单封装,适合精确控制的任务。
|
|||
|
// 用法: ThreadController::getInstance()->work(workCall, resultCall)
|
|||
|
// workCall是在新线程中执行的任务,resultCall是任务执行完成后,回到调用线程中用来处理执行结果。
|
|||
|
// work函数返回值为任务id。
|
|||
|
// 取消任务用ThreadController::getInstance()->cancle(id)函数。
|
|||
|
class ThreadWorker : public QObject
|
|||
|
{
|
|||
|
Q_OBJECT
|
|||
|
public:
|
|||
|
ThreadWorker(uint64_t id, const WorkCallback &workCall, QObject *parent = nullptr) : QObject(parent), m_id(id), m_workCall(workCall) {}
|
|||
|
|
|||
|
signals:
|
|||
|
void workFinished(bool, uint64_t);
|
|||
|
public slots:
|
|||
|
void doWork()
|
|||
|
{
|
|||
|
bool ret = m_workCall();
|
|||
|
emit workFinished(ret, m_id);
|
|||
|
}
|
|||
|
private:
|
|||
|
const uint64_t m_id;
|
|||
|
WorkCallback m_workCall;
|
|||
|
};
|
|||
|
class TAO_API ThreadController : public QObject
|
|||
|
{
|
|||
|
Q_OBJECT
|
|||
|
public:
|
|||
|
static ThreadController *getInstance()
|
|||
|
{
|
|||
|
static ThreadController controller;
|
|||
|
return &controller;
|
|||
|
}
|
|||
|
|
|||
|
~ThreadController()
|
|||
|
{
|
|||
|
for (auto k : m_threadMap.uniqueKeys())
|
|||
|
{
|
|||
|
if (m_threadMap.value(k)->isRunning())
|
|||
|
{
|
|||
|
m_threadMap.value(k)->quit();
|
|||
|
m_threadMap.value(k)->wait();
|
|||
|
}
|
|||
|
}
|
|||
|
qDeleteAll(m_threadMap);
|
|||
|
m_threadMap.clear();
|
|||
|
m_resultCallback.clear();
|
|||
|
}
|
|||
|
uint64_t work(const WorkCallback &workCall, const WorkResultCallback &resultCall)
|
|||
|
{
|
|||
|
QThread *thread = new QThread;
|
|||
|
m_rollId++;
|
|||
|
ThreadWorker *obj = new ThreadWorker(m_rollId, workCall);
|
|||
|
m_threadMap[m_rollId] = thread;
|
|||
|
m_resultCallback[m_rollId] = resultCall;
|
|||
|
obj->moveToThread(thread);
|
|||
|
|
|||
|
connect(thread, &QThread::finished, obj, &QObject::deleteLater);
|
|||
|
connect(thread, &QThread::started, obj, &ThreadWorker::doWork);
|
|||
|
connect(obj, &ThreadWorker::workFinished, this, &ThreadController::onWorkFinished, Qt::QueuedConnection);
|
|||
|
thread->start();
|
|||
|
return m_rollId;
|
|||
|
}
|
|||
|
void cancle(uint64_t id)
|
|||
|
{
|
|||
|
auto it = m_threadMap.find(id);
|
|||
|
if (it != m_threadMap.end())
|
|||
|
{
|
|||
|
if ((*it)->isRunning())
|
|||
|
{
|
|||
|
(*it)->terminate();
|
|||
|
}
|
|||
|
}
|
|||
|
m_resultCallback.remove(id);
|
|||
|
}
|
|||
|
void quit(uint64_t id)
|
|||
|
{
|
|||
|
auto it = m_threadMap.find(id);
|
|||
|
if (it != m_threadMap.end())
|
|||
|
{
|
|||
|
if ((*it)->isRunning())
|
|||
|
{
|
|||
|
(*it)->quit();
|
|||
|
(*it)->wait();
|
|||
|
(*it)->deleteLater();
|
|||
|
}
|
|||
|
}
|
|||
|
m_resultCallback.remove(id);
|
|||
|
}
|
|||
|
QList<uint64_t> getAllWorkId() const
|
|||
|
{
|
|||
|
return m_threadMap.uniqueKeys();
|
|||
|
}
|
|||
|
protected slots :
|
|||
|
void onWorkFinished(bool ok, uint64_t id)
|
|||
|
{
|
|||
|
auto it = m_threadMap.find(id);
|
|||
|
if (it != m_threadMap.end())
|
|||
|
{
|
|||
|
if ((*it)->isRunning())
|
|||
|
{
|
|||
|
(*it)->quit();
|
|||
|
(*it)->wait();
|
|||
|
(*it)->deleteLater();
|
|||
|
}
|
|||
|
m_threadMap.remove(id);
|
|||
|
}
|
|||
|
auto caller = m_resultCallback.find(id);
|
|||
|
if (caller != m_resultCallback.end())
|
|||
|
{
|
|||
|
(*caller)(ok);
|
|||
|
m_resultCallback.remove(id);
|
|||
|
}
|
|||
|
}
|
|||
|
protected:
|
|||
|
ThreadController(QObject *parent = nullptr) : QObject(parent) {}
|
|||
|
|
|||
|
private:
|
|||
|
uint64_t m_rollId = 0;
|
|||
|
QMap<uint64_t, QThread *> m_threadMap;
|
|||
|
QMap<uint64_t, WorkResultCallback> m_resultCallback;
|
|||
|
};
|
|||
|
} // namespace LCIM
|