#include "TaskManager.h" #include "WindowAppTaskView.h" #include "Pou.h" #include "Preferences.h" #include "PouManager.h" #include "GvlManager.h" TaskManager* TaskManager::m_pTaskManager = nullptr; // 同时支持的Task最大线程数 #define MAX_TASK_THREAD 20 TaskManager::TaskManager() { // 支持线程池最大并行线程 m_TaskThreadPool.setMaxThreadCount(MAX_TASK_THREAD); // 注册自定义线程参数 // (切记需要注册,如果不注册的话线程参数不会正常传递到线程中执行) // qRegisterMetaType("TASK*"); qRegisterMetaType>("QVector"); // 生成系统内置事件 this->initSysEvents(); // 初始化系统定时器 m_eventTimer.setInterval(SYS_TIMER); connect(&m_eventTimer, SIGNAL(timeout()), this, SLOT(onEventTimer())); } /// /// 接收来自各个View的Task注册信息 /// /// /// void TaskManager::registerTask(TASK* pTask, WindowAppTaskView* pView) { m_Tasks.insert(pTask->strName, pTask); m_TaskViews.insert(pTask->strName, pView); // 有了新的Task,更新一下Task和event的对应关系 if (pTask->pEvent != nullptr) { m_EventTasks.insertMulti(pTask->pEvent->type(), pTask); } } ///// ///// 添加单独的Task ///// ///// //void TaskManager::addTask(TASK* pNewTask) //{ // pNewTask->nIndex = m_Tasks.size(); // m_Tasks.insert(pNewTask->strName, pNewTask); //} ///// ///// 新建一个Task ///// ///// //void TaskManager::addTask(const QString& strTaskName) //{ // TASK newTask; // // newTask.nIndex = m_Tasks.size(); // newTask.strName = strTaskName; // // m_Tasks.insert(strTaskName, newTask); //} /// /// 为指定的Task添加Pou /// /// /// void TaskManager::addTaskPous(const QString& strTaskName, const QVector& pous) { if (m_Tasks.find(strTaskName) != m_Tasks.end()) { m_Tasks.value(strTaskName)->pous.append(pous); } else { qWarning() << "[Error] addTaskPous, but can't find the task, name :" << strTaskName; } } /// /// 删除整个Task /// /// void TaskManager::delTask(const QString& strTaskName) { // 枚举Task中的每一个Task,并清理标记位 QVectorIterator it(m_Tasks.value(strTaskName)->pous); while (it.hasNext()) { POU* pPou = it.next(); pPou->m_pParentTask = nullptr; } m_Tasks.remove(strTaskName); m_TaskViews.remove(strTaskName); // TODO:需要删除event QHashIterator i(m_EventTasks); while (i.hasNext()) { QList pTasks = m_EventTasks.values(i.next().key()); for (TASK* pTask : pTasks) { if (pTask->strName == strTaskName) { m_EventTasks.remove(i.key(), pTask); break; } } } } /// /// 删除指定Task中的一个Pou /// /// /// void TaskManager::delTaskPou(const QString& strTaskName, const int& nPouIndex) { m_Tasks.value(strTaskName)->pous.remove(nPouIndex); } /// /// 数据结构重置 /// void TaskManager::reset() { m_Tasks.clear(); m_TaskViews.clear(); m_EventTasks.clear(); m_EventTools.clear(); m_ToolEvents.clear(); } /// /// Pou信息交换顺序 /// /// /// /// void TaskManager::swapTaskPou(const QString& strTaskName, const int& nIndex1, const int& nIndex2) { qSwap(m_Tasks.value(strTaskName)->pous[nIndex1], m_Tasks.value(strTaskName)->pous[nIndex2]); //PouManager* pTmp = m_Tasks.value(strTaskName).pous[nIndex2]; //m_Tasks.value(strTaskName).pous[nIndex1] = m_Tasks.value(strTaskName).pous[nIndex2]; //m_Tasks.value(strTaskName).pous[nIndex2] = pTmp; } //============================================================ // // Task执行相关 // //============================================================ /// /// 执行所有任务 /// /// 是否只执行一轮 bool TaskManager::executeAllTasks(bool bOnce) { Q_UNUSED(bOnce); // 检查是否有Task处于Busy状态 if (isTaskBusy()) { return false; } // 设定系统内置事件定时器 if (!m_eventTimer.isActive()) { // 启动定时器 m_eventTimer.start(); } // 重置时间计数器 m_nTimerCounter = 0; // 循环所有任务启动执行 QMap::iterator iter = m_Tasks.begin(); while (iter != m_Tasks.end()) { this->executeTask(iter.key(), bOnce); iter++; } return true; } /// /// 执行Task /// /// 待执行任务的名字 /// 是否是单次执行 void TaskManager::executeTask(const QString& strTaskName, bool bOnce /*= true*/) { // 确保任务的名字正确 if (m_Tasks.find(strTaskName) == m_Tasks.end()) { qWarning() << "[Error] executeTask, but can't find the task, name :" << strTaskName; return; } // 检查任务的状态是否为busy if (isTaskBusy(strTaskName)) { return; } // 启动线程开始执行对应的Task if (bOnce) { m_Tasks.value(strTaskName)->execParams.runMode = TASK_RUN_MODE::RUN_ONCE; } else { m_Tasks.value(strTaskName)->execParams.runMode = TASK_RUN_MODE::RUN_LOOP; } // 设置线程参数 qDebug() << "[TASK] Run task[" << strTaskName << "] thread pool...."; // 启动线程(带Task线程优先级) m_TaskThreadPool.start( new _TaskThread(m_Tasks.value(strTaskName)), (int)m_Tasks.value(strTaskName)->execParams.nPriority ); } /// /// 执行Task(供线程调用) /// /// /// void TaskManager::_executeTask(TASK* pTask) { thePrefs.m_bSystemIsRunning = true; qDebug() << "[TASK] Run thread task[" << pTask->strName << "] _executeTask in mode:" << (short)pTask->execParams.runMode; WindowAppTaskView* pView = m_TaskViews.value(pTask->strName); // 重置一下Task的Timer pTask->execParams.nExecTime = 0; // 开始统计Task 执行时间 QElapsedTimer taskTimer; // 循环执行 forever { // 等到事件前,开始计时 taskTimer.start(); // 将Task置为Wait状态 pTask->execParams.nStatus = VPEnum::EXEC_STATUS::Wait; emit pView->sigUpdateTaskStatus(); // vDebug() << "Task[" << pTask->strName << "] waiting..."; // 如果是事件任务,则等待Task事件触发后才执行 bool bWaitDone = this->waitForEvents(pTask); // Q_UNUSED(bWaitDone); // vDebug() << "Task[" << pTask->strName << "] waiting finished."; // 等到事件后,开始计时 taskTimer.start(); // 2021-9-29 此处的判断还是需要打开,防止waitForEvents返回false时,task依然继续执行的问题 if (!bWaitDone) { // 检查一下线程是否退出 if (pTask->execParams.runMode == TASK_RUN_MODE::RUN_STOP) { this->setTaskStandBy(pTask, pView); break; } else { continue; } } qDebug() << "----- [TASK] Task[" << pTask->strName << "] activate."; // 将Task置为Busy状态 pTask->execParams.nStatus = VPEnum::EXEC_STATUS::Busy; emit pView->sigUpdateTaskStatus(); // 枚举Task中的每一个Pou,顺序执行 QVectorIterator it(pTask->pous); while (it.hasNext()) { POU* pPou = it.next(); this->_executePou(pTask, pPou, pView); } // 如果Task任务退出则退出循环 if (pTask->execParams.runMode == TASK_RUN_MODE::RUN_STOP) { this->setTaskStandBy(pTask, pView); break; } //只执行一次的话,退出循环 else if (pTask->execParams.runMode == TASK_RUN_MODE::RUN_ONCE) { this->setTaskDone(pTask, taskTimer, pView); break; } // 执行Task后延时 Utility::qSleep(pTask->execParams.nPostDelay); // Task Done this->setTaskDone(pTask, taskTimer, pView); qDebug() << "----- [TASK] Task[" << pTask->strName << "] finished."; } thePrefs.m_bSystemIsRunning = false; // Task Done 吗, //this->setTaskDone(pTask, pView); qDebug() << "[TASK][Thread] Task[" << pTask->strName << "] _executeTask exit."; } /// /// 执行Pou(线程执行) /// /// /// void TaskManager::_executePou(TASK* pTask, POU* pPou, WindowAppTaskView* pView) { // 开始统计 pou 执行时间 QElapsedTimer pouTimer; pouTimer.start(); //// For Test //Utility::qSleep(200); // 将Pou置为busy状态 this->setPouBusy(pPou, pView); // 以Tool为单位执行 const QVector& allTools = pPou->GetAllStandardTools(); for (int index = 0; index < allTools.size(); ) { TOOL* pTool = allTools[index]; // Tool Busy this->setToolBusy(pPou, pTool, pView); // 开始统计Tool执行时间 QElapsedTimer toolTimer; toolTimer.start(); VPEnum::RETURN_VALUE ret = VPEnum::RETURN_VALUE::None; // 交给Pou的Tool执行调度器执行 ret = pPou->ToolExecutionDispatcher(pTool, index, TOOL_RUN_MODE::SEQUENTIAL); // 如果出现了错误,则Task的错误值需要 + 1 (Success和Goto混在一起判断了) if (ret != VPEnum::RETURN_VALUE::Success && ret != VPEnum::RETURN_VALUE::Goto) { pTask->execParams.nErrorCount++; } // 工具完成,执行更新 this->setToolDone(pPou, pTool, toolTimer, pView); qDebug() << "[TASK:" << pTask->strName << "][POU:" << pPou->pouName() << "][Tool:" << pTool->strInstanceName << "][Index:" << pTool->nIndex << "] executed finished."; } // Pou完成,执行更新 this->setPouDone(pPou, pouTimer, pView); } /// /// 停止所有任务 /// /// 是否强制停止 void TaskManager::stopAllTask(bool bForce /*= false*/) { Q_UNUSED(bForce); //// 检查是否有Task处于Busy状态 //if (! isTaskBusy ()) //{ // return; //} // 设定系统内置事件定时器 if (m_eventTimer.isActive()) { // 启动定时器 m_eventTimer.stop(); } // 重置时间计数器 m_nTimerCounter = 0; // 2022-9-4 循环所有Tool的activator,发送退出信号 QMutableHashIterator iter(m_EventTools); while (iter.hasNext()) { QList tools = m_EventTools.values(iter.next().key()); foreach(TOOL* tool, tools) { tool->activator.wakeAll(); } } // 循环所有Task,发送任务退出信号 QMap::iterator iter2 = m_Tasks.begin(); while (iter2 != m_Tasks.end()) { TASK* pTask = iter2.value(); pTask->execParams.runMode = TASK_RUN_MODE::RUN_STOP; pTask->activator.wakeAll(); iter2++; } } /// /// 检查Task状态是否Busy /// /// /// bool TaskManager::isTaskBusy(const QString& strTaskName /*= ""*/) { // 如果名字是空,则是检查所有任务的 if (strTaskName.isEmpty()) { QMap::iterator iter = m_Tasks.begin(); while (iter != m_Tasks.end()) { if (iter.value()->execParams.nStatus == VPEnum::EXEC_STATUS::Busy) { //Utility::VPCriticalMessageBox("Task [" + iter.value()->strName + "] is busy!"); return true; } iter++; } } else { if (m_Tasks.value(strTaskName)->execParams.nStatus == VPEnum::EXEC_STATUS::Busy) { //Utility::VPCriticalMessageBox("Task [" + strTaskName + "] is busy!"); return true; } } return thePrefs.m_bSystemIsRunning; } /// /// 为TaskView添加一个新的Tool(用于Pou中动态增加Tool同步更新信息) /// /// /// /// void TaskManager::addToolToTaskView(const QString& strTaskName, const POU* pPou, const TOOL* pTool) { // 首先找到对应的TaskView WindowAppTaskView* pView = m_TaskViews.value(strTaskName); pView->addTaskPouTool(pPou, pTool); } /// /// 执行Task的Event等待任务 /// /// bool TaskManager::waitForEvents(TASK* pTask) { // Loop执行或者是只执行一次,是不需要等待事件的 if (pTask->strModeName == TASK_MODE_LOOP || pTask->execParams.runMode == TASK_RUN_MODE::RUN_ONCE) { //Utility::qSleep(50); return true; } //qDebug() << "[TASK] " << pTask->strName << " Wait for event[" << pTask->strMode << "]"; // 否则开始等待任务事件触发 pTask->mutex.lock(); if (pTask->activator.wait(&pTask->mutex, pTask->timeOut) == false) { pTask->mutex.unlock(); return false; } pTask->mutex.unlock(); return true; } /// /// 2021-8-21 更新,Task设置更新后,要及时更新 m_TaskEvents 中的Event和Task的对应关系 /// /// void TaskManager::updateTaskEvent(QEvent::Type oldType, TASK* pTask) { // 删除旧的event-task绑定关系 m_EventTasks.remove(oldType, pTask); // 有了新的Task,更新一下Task和event的对应关系 if (pTask->pEvent != nullptr) { m_EventTasks.insertMulti(pTask->pEvent->type(), pTask); } } /// /// 2022-9-4 为了实现事件触发Tool等待执行而增加的系列函数 /// /// /// void TaskManager::registerToolEvent(ToolEvent* event, TOOL* tool) { m_EventTools.insertMulti(event->type(), tool); m_ToolEvents.insert(tool, event); } /// /// 查询本工具是否绑定了触发事件 /// /// bool TaskManager::isToolTriggerable(TOOL* pTool) { QMutableHashIterator iter(m_EventTools); while (iter.hasNext()) { QList tools = m_EventTools.values(iter.next().key()); foreach(TOOL * tool, tools) { if (pTool == tool) { return true; } } } return false; } /// /// // 删除了一个工具的时候,需要到这里来反注册一下 /// /// void TaskManager::unregisterTool(TOOL* pTool) { QMutableHashIterator iter(m_EventTools); while (iter.hasNext()) { QList tools = m_EventTools.values(iter.next().key()); foreach(TOOL * tool, tools) { if (pTool == tool) { m_EventTools.remove(iter.key(), pTool); return; } } } m_ToolEvents.remove(pTool); } /// /// 通过Tool查询ToolEvents信息(目前用于序列化中) /// /// /// ToolEvent* TaskManager::getEventByTool(TOOL* pTool) { return m_ToolEvents.value(pTool); } //============================================================ // // Task界面设置 相关 // //============================================================ /// /// 设置tool为Busy状态 /// /// /// void TaskManager::setToolBusy(const POU* pPou, TOOL* pTool, WindowAppTaskView* pView) { pTool->execParams.nStatus = VPEnum::EXEC_STATUS::Busy; emit pView->sigUpdateToolStatus(pPou, pTool); } /// /// 设置tool为完成状态 /// /// void TaskManager::setToolDone( POU* pPou, TOOL* pTool, QElapsedTimer& toolTimer, WindowAppTaskView* pView ) { int nTimer = toolTimer.elapsed(); // 统计Tool执行时间 pTool->execParams.nExecTime = nTimer; // Tool Done pTool->execParams.nStatus = VPEnum::EXEC_STATUS::Done; // 2022-8-29 由于执行次数各个工具内部的情况都不一样,干脆还是直接改回工具内部处理了 //// 正常情况下,Tool 执行次数+1(需要排除掉Goto和ForLoop特殊处理) //if ((!pTool->isGotoTool()) && (!pTool->isForloopTool())) //{ // pTool->execParams.nExecCount++; //} //// 2022-4-6增加,Goto工具只有在执行了Goto动作后执行次数才会 +1 //else if (pTool->isGotoTool() // && pTool->execParams.nRetValue == VPEnum::RETURN_VALUE::Goto) //{ // pTool->execParams.nExecCount++; //} //// 2022-8-28 增加,ForLoop工具的执行计数需要按照其循环执行的次数来+,所以只能在ForLoop工具内部处理 //else if (pTool->isForloopTool()) //{ //} // 刷新所有表格 emit pView->sigUpdateAllTables(pPou, pTool); } /// /// 设置Pou为Busy状态 /// /// /// void TaskManager::setPouBusy(POU* pPou, WindowAppTaskView* pView) { // 将Pou置为busy状态 pPou->execParams.nStatus = VPEnum::EXEC_STATUS::Busy; emit pView->sigUpdatePouStatus(pPou); // 重置一下Pou的Timer pPou->execParams.nExecTime = 0; } /// /// 设置Pou为完成状态 /// /// void TaskManager::setPouDone(POU* pPou, QElapsedTimer& pouTimer, WindowAppTaskView* pView) { // 将Pou置为完成状态 pPou->execParams.nStatus = VPEnum::EXEC_STATUS::Done; // Pou 执行次数+1 pPou->execParams.nExecCount++; // 结束统计Pou执行时间 pPou->execParams.nExecTime = pouTimer.elapsed(); VARIABLE* pVar = g_pGvlManager->getVariableByName(pPou->pouName(), INTERNALVAR_NAME_EXECTIME); QString strValue = pVar->getValueString(); // 更新一下Pou表格和Task表格 emit pView->sigUpdatePouTable(pPou); // 2022-3-21,检查Pou内部变量是否绑定了复杂控件的索引(或刷新)并执行更新 this->syncComplexIndexToRuntime(pPou->pouName()); // 2022-9-10,发送Pou同步消息 this->syncPouParamsToUi(pPou); } /// /// 设置Task为完成状态 /// /// void TaskManager::setTaskDone(TASK* pTask, QElapsedTimer& taskTimer, WindowAppTaskView* pView) { // 全部Pou执行完毕后,将Task置为Done状态 pTask->execParams.nStatus = VPEnum::EXEC_STATUS::Done; // Task执行次数 + 1 pTask->execParams.nExecCount++; // 系统中的总执行次数 +1 thePrefs.m_nRunningCount++; // 统计Task执行时间 pTask->execParams.nExecTime = taskTimer.elapsed(); // 刷新Task表格 emit pView->sigUpdateTaskTable(); // 2022-9-10,发送Task同步消息(向UI) this->syncTaskAndSystemParamsToUi(pTask); // 2022-9-12,检查全局变量是否绑定了复杂控件的索引并执行更新(向Runtime) this->syncComplexIndexToRuntime(GROUP_NAME_SYSTEM); } /// /// 设置Task为就绪状态 /// /// void TaskManager::setTaskStandBy(TASK* pTask, WindowAppTaskView* pView) { // 全部Pou执行完毕后,将Task置为Done状态 pTask->execParams.nStatus = VPEnum::EXEC_STATUS::StandBy; // 刷新Task表格 emit pView->sigUpdateTaskTable(); } /// /// 2022-9-10,增加了Task完成时的数值触发动作,用于提供给外部进行绑定同步 /// void TaskManager::syncTaskAndSystemParamsToUi(TASK* pTask) { SyncValueEvent* valueEvent = new SyncValueEvent(); // Task执行次数 VARIABLE* pVar = g_pGvlManager->getVariableByName(GROUP_NAME_SYSTEM, pTask->strName + EXEC_COUNT_POSTFIX); valueEvent->addSyncValue(pVar); // System执行总次数 pVar = g_pGvlManager->getVariableByName(GROUP_NAME_SYSTEM, SYSTEMVAR_NAME_EXECCOUNT); valueEvent->addSyncValue(pVar); // TODO:其他参数由于没有变动,为了提高效率这里就没有触发,也就是说如果绑定其他参数的话,变动的时候应该不会得到同步 // 更合理的方式应该是在其他变量变动的时候再同步即可,放在这里效率有点低了 // post数值同步消息,post内部会自动释放event的指针,无需手工释放 QCoreApplication::postEvent((QObject*)g_pUiManager, valueEvent); } /// /// 2022-9-10,增加了Pou完成时的数值触发动作,用于提供给外部进行绑定同步 /// void TaskManager::syncPouParamsToUi(POU* pPou) { SyncValueEvent* valueEvent = new SyncValueEvent(); // Pou的执行次数 VARIABLE* pVar = g_pGvlManager->getVariableByName(pPou->pouName(), INTERNALVAR_NAME_EXECCOUNT); valueEvent->addSyncValue(pVar); // Pou执行时间 pVar = g_pGvlManager->getVariableByName(pPou->pouName(), INTERNALVAR_NAME_EXECTIME); valueEvent->addSyncValue(pVar); // post数值同步消息,post内部会自动释放event的指针,无需手工释放 QCoreApplication::postEvent((QObject*)g_pUiManager, valueEvent); } //============================================================ // // Event 相关 // //============================================================ /// /// 初始化系统事件 /// void TaskManager::initSysEvents() { // 为了统一事件触发机制,把系统内置变量的Event机制进行了重写 _INTERFACE* newEventInf = new _INTERFACE(nullptr); // Task_loop(为了统一也作为一个事件,但是指针为nullptr) newEventInf->strName = (TASK_MODE_LOOP); newEventInf->strFullName = (TASK_MODE_LOOP); newEventInf->Direction = INF_DIRECTION::INF_DIR_OUT; newEventInf->Type = INF_TYPE::INF_TYPE_EVENT; newEventInf->eventTrigger = nullptr; m_sysEvents.insert(newEventInf->strFullName, newEventInf); // Task Run newEventInf = new _INTERFACE(nullptr); newEventInf->strName = (TASK_MODE_EVENT_RUN); newEventInf->strFullName = (TASK_MODE_EVENT_RUN); newEventInf->Direction = INF_DIRECTION::INF_DIR_OUT; newEventInf->Type = INF_TYPE::INF_TYPE_EVENT; newEventInf->eventTrigger = new ToolEvent(GROUP_NAME_SYSTEMEVENT, newEventInf->strFullName, TOOL_EVENT_TYPE::TASK_TRIGGER); m_sysEvents.insert(newEventInf->strFullName, newEventInf); // Task Stop newEventInf = new _INTERFACE(nullptr); newEventInf->strName = (TASK_MODE_EVENT_STOP); newEventInf->strFullName = (TASK_MODE_EVENT_STOP); newEventInf->Direction = INF_DIRECTION::INF_DIR_OUT; newEventInf->Type = INF_TYPE::INF_TYPE_EVENT; newEventInf->eventTrigger = new ToolEvent(GROUP_NAME_SYSTEMEVENT, newEventInf->strFullName, TOOL_EVENT_TYPE::TASK_TRIGGER); m_sysEvents.insert(newEventInf->strFullName, newEventInf); // Sys Exit newEventInf = new _INTERFACE(nullptr); newEventInf->strName = (TASK_MODE_EVENT_EXIT); newEventInf->strFullName = (TASK_MODE_EVENT_EXIT); newEventInf->Direction = INF_DIRECTION::INF_DIR_OUT; newEventInf->Type = INF_TYPE::INF_TYPE_EVENT; newEventInf->eventTrigger = new ToolEvent(GROUP_NAME_SYSTEMEVENT, newEventInf->strFullName, TOOL_EVENT_TYPE::TASK_TRIGGER); m_sysEvents.insert(newEventInf->strFullName, newEventInf); // Load Doc newEventInf = new _INTERFACE(nullptr); newEventInf->strName = (TASK_MODE_EVENT_DOCLOADED); newEventInf->strFullName = (TASK_MODE_EVENT_DOCLOADED); newEventInf->Direction = INF_DIRECTION::INF_DIR_OUT; newEventInf->Type = INF_TYPE::INF_TYPE_EVENT; newEventInf->eventTrigger = new ToolEvent(GROUP_NAME_SYSTEMEVENT, newEventInf->strFullName, TOOL_EVENT_TYPE::TASK_TRIGGER); m_sysEvents.insert(newEventInf->strFullName, newEventInf); // 100ms newEventInf = new _INTERFACE(nullptr); newEventInf->strName = (TASK_MODE_EVENT_TIME_100MS); newEventInf->strFullName = (TASK_MODE_EVENT_TIME_100MS); newEventInf->Direction = INF_DIRECTION::INF_DIR_OUT; newEventInf->Type = INF_TYPE::INF_TYPE_EVENT; newEventInf->eventTrigger = new ToolEvent(GROUP_NAME_SYSTEMEVENT, newEventInf->strFullName, TOOL_EVENT_TYPE::TASK_TRIGGER); m_sysEvents.insert(newEventInf->strFullName, newEventInf); // 500ms newEventInf = new _INTERFACE(nullptr); newEventInf->strName = (TASK_MODE_EVENT_TIME_500MS); newEventInf->strFullName = (TASK_MODE_EVENT_TIME_500MS); newEventInf->Direction = INF_DIRECTION::INF_DIR_OUT; newEventInf->Type = INF_TYPE::INF_TYPE_EVENT; newEventInf->eventTrigger = new ToolEvent(GROUP_NAME_SYSTEMEVENT, newEventInf->strFullName, TOOL_EVENT_TYPE::TASK_TRIGGER); m_sysEvents.insert(newEventInf->strFullName, newEventInf); // 1s newEventInf = new _INTERFACE(nullptr); newEventInf->strName = (TASK_MODE_EVENT_TIME_1S); newEventInf->strFullName = (TASK_MODE_EVENT_TIME_1S); newEventInf->Direction = INF_DIRECTION::INF_DIR_OUT; newEventInf->Type = INF_TYPE::INF_TYPE_EVENT; newEventInf->eventTrigger = new ToolEvent(GROUP_NAME_SYSTEMEVENT, newEventInf->strFullName, TOOL_EVENT_TYPE::TASK_TRIGGER); m_sysEvents.insert(newEventInf->strFullName, newEventInf); // 5s newEventInf = new _INTERFACE(nullptr); newEventInf->strName = (TASK_MODE_EVENT_TIME_5S); newEventInf->strFullName = (TASK_MODE_EVENT_TIME_5S); newEventInf->Direction = INF_DIRECTION::INF_DIR_OUT; newEventInf->Type = INF_TYPE::INF_TYPE_EVENT; newEventInf->eventTrigger = new ToolEvent(GROUP_NAME_SYSTEMEVENT, newEventInf->strFullName, TOOL_EVENT_TYPE::TASK_TRIGGER); m_sysEvents.insert(newEventInf->strFullName, newEventInf); // Old //// 构造Event类型的接口,为了和Tool中的Event接口统一 //_INTERFACE* newEventInf = new _INTERFACE(nullptr); //// Task_loop(为了统一也作为一个事件,但是指针为nullptr) //newEventInf->strName = (TASK_MODE_LOOP); //newEventInf->strFullName = (TASK_MODE_LOOP); //newEventInf->Direction = INF_DIRECTION::INF_DIR_OUT; //newEventInf->Type = INF_TYPE::INF_TYPE_STANDARD; //newEventInf->value.passMode = VALUE_PASS_MODE::PASS_BY_VALUE; //newEventInf->value.type = VALUE_TYPE::Type_Event; //newEventInf->value.Ptr = nullptr; //m_sysModes.insert(newEventInf->strName, newEventInf); //// Task Run //newEventInf = new _INTERFACE(nullptr); //newEventInf->strName = (TASK_MODE_EVENT_RUN); //newEventInf->strFullName = (TASK_MODE_EVENT_RUN); //newEventInf->Direction = INF_DIRECTION::INF_DIR_OUT; //newEventInf->Type = INF_TYPE::INF_TYPE_STANDARD; //newEventInf->value.passMode = VALUE_PASS_MODE::PASS_BY_VALUE; //newEventInf->value.type = VALUE_TYPE::Type_Event; //newEventInf->value.Ptr = (void**)( // new ToolEvent(GROUP_NAME_SYSTEMEVENT, newEventInf->strFullName, TOOL_EVENT_TYPE::TRIGGER_TASK_THREAD) // ); //m_sysModes.insert(newEventInf->strName, newEventInf); //// Task Stop //newEventInf = new _INTERFACE(nullptr); //newEventInf->strName = (TASK_MODE_EVENT_STOP); //newEventInf->strFullName = (TASK_MODE_EVENT_STOP); //newEventInf->Direction = INF_DIRECTION::INF_DIR_OUT; //newEventInf->Type = INF_TYPE::INF_TYPE_STANDARD; //newEventInf->value.passMode = VALUE_PASS_MODE::PASS_BY_VALUE; //newEventInf->value.type = VALUE_TYPE::Type_Event; //newEventInf->value.Ptr = (void**)( // new ToolEvent(GROUP_NAME_SYSTEMEVENT, newEventInf->strFullName, TOOL_EVENT_TYPE::TRIGGER_TASK_THREAD) // ); //m_sysModes.insert(newEventInf->strName, newEventInf); //// Sys Exit //newEventInf = new _INTERFACE(nullptr); //newEventInf->strName = (TASK_MODE_EVENT_EXIT); //newEventInf->strFullName = (TASK_MODE_EVENT_EXIT); //newEventInf->Direction = INF_DIRECTION::INF_DIR_OUT; //newEventInf->Type = INF_TYPE::INF_TYPE_STANDARD; //newEventInf->value.passMode = VALUE_PASS_MODE::PASS_BY_VALUE; //newEventInf->value.type = VALUE_TYPE::Type_Event; //newEventInf->value.Ptr = (void**)( // new ToolEvent(GROUP_NAME_SYSTEMEVENT, newEventInf->strFullName, TOOL_EVENT_TYPE::TRIGGER_TASK_THREAD) // ); //m_sysModes.insert(newEventInf->strName, newEventInf); //// Load Doc //newEventInf = new _INTERFACE(nullptr); //newEventInf->strName = (TASK_MODE_EVENT_DOCLOADED); //newEventInf->strFullName = (TASK_MODE_EVENT_DOCLOADED); //newEventInf->Direction = INF_DIRECTION::INF_DIR_OUT; //newEventInf->Type = INF_TYPE::INF_TYPE_STANDARD; //newEventInf->value.passMode = VALUE_PASS_MODE::PASS_BY_VALUE; //newEventInf->value.type = VALUE_TYPE::Type_Event; //newEventInf->value.Ptr = (void**)( // new ToolEvent(GROUP_NAME_SYSTEMEVENT, newEventInf->strFullName, TOOL_EVENT_TYPE::TRIGGER_TASK_THREAD) // ); //m_sysModes.insert(newEventInf->strName, newEventInf); //// 100ms //newEventInf = new _INTERFACE(nullptr); //newEventInf->strName = (TASK_MODE_EVENT_TIME_100MS); //newEventInf->strFullName = (TASK_MODE_EVENT_TIME_100MS); //newEventInf->Direction = INF_DIRECTION::INF_DIR_OUT; //newEventInf->Type = INF_TYPE::INF_TYPE_STANDARD; //newEventInf->value.passMode = VALUE_PASS_MODE::PASS_BY_VALUE; //newEventInf->value.type = VALUE_TYPE::Type_Event; //newEventInf->value.Ptr = (void**)( // new ToolEvent(GROUP_NAME_SYSTEMEVENT, newEventInf->strFullName, TOOL_EVENT_TYPE::TRIGGER_TASK_THREAD) // ); //m_sysModes.insert(newEventInf->strName, newEventInf); //// 500ms //newEventInf = new _INTERFACE(nullptr); //newEventInf->strName = (TASK_MODE_EVENT_TIME_500MS); //newEventInf->strFullName = (TASK_MODE_EVENT_TIME_500MS); //newEventInf->Direction = INF_DIRECTION::INF_DIR_OUT; //newEventInf->Type = INF_TYPE::INF_TYPE_STANDARD; //newEventInf->value.passMode = VALUE_PASS_MODE::PASS_BY_VALUE; //newEventInf->value.type = VALUE_TYPE::Type_Event; //newEventInf->value.Ptr = (void**)( // new ToolEvent(GROUP_NAME_SYSTEMEVENT, newEventInf->strFullName, TOOL_EVENT_TYPE::TRIGGER_TASK_THREAD) // ); //m_sysModes.insert(newEventInf->strName, newEventInf); //// 1s //newEventInf = new _INTERFACE(nullptr); //newEventInf->strName = (TASK_MODE_EVENT_TIME_1S); //newEventInf->strFullName = (TASK_MODE_EVENT_TIME_1S); //newEventInf->Direction = INF_DIRECTION::INF_DIR_OUT; //newEventInf->Type = INF_TYPE::INF_TYPE_STANDARD; //newEventInf->value.passMode = VALUE_PASS_MODE::PASS_BY_VALUE; //newEventInf->value.type = VALUE_TYPE::Type_Event; //newEventInf->value.Ptr = (void**)( // new ToolEvent(GROUP_NAME_SYSTEMEVENT, newEventInf->strFullName, TOOL_EVENT_TYPE::TRIGGER_TASK_THREAD) // ); //m_sysModes.insert(newEventInf->strName, newEventInf); //// 5s //newEventInf = new _INTERFACE(nullptr); //newEventInf->strName = (TASK_MODE_EVENT_TIME_5S); //newEventInf->strFullName = (TASK_MODE_EVENT_TIME_5S); //newEventInf->Direction = INF_DIRECTION::INF_DIR_OUT; //newEventInf->Type = INF_TYPE::INF_TYPE_STANDARD; //newEventInf->value.passMode = VALUE_PASS_MODE::PASS_BY_VALUE; //newEventInf->value.type = VALUE_TYPE::Type_Event; //newEventInf->value.Ptr = (void**)( // new ToolEvent(GROUP_NAME_SYSTEMEVENT, newEventInf->strFullName, TOOL_EVENT_TYPE::TRIGGER_TASK_THREAD) // ); //m_sysModes.insert(newEventInf->strName, newEventInf); } /// /// 定时器Even事件 /// void TaskManager::onEventTimer() { // 100ms if (m_sysEvents.contains(TASK_MODE_EVENT_TIME_100MS)) { ToolEvent* pEvent = (ToolEvent*)m_sysEvents.value(TASK_MODE_EVENT_TIME_100MS)->eventTrigger; QCoreApplication::sendEvent(this, pEvent); } // 500ms if (m_nTimerCounter % 5 == 0) { if (m_sysEvents.contains(TASK_MODE_EVENT_TIME_500MS)) { ToolEvent* pEvent = (ToolEvent*)m_sysEvents.value(TASK_MODE_EVENT_TIME_500MS)->eventTrigger; QCoreApplication::sendEvent(this, pEvent); } } //1s if (m_nTimerCounter % 10 == 0) { if (m_sysEvents.contains(TASK_MODE_EVENT_TIME_1S)) { ToolEvent* pEvent = (ToolEvent*)m_sysEvents.value(TASK_MODE_EVENT_TIME_1S)->eventTrigger; QCoreApplication::sendEvent(this, pEvent); } } //5s if (m_nTimerCounter % 50 == 0) { if (m_sysEvents.contains(TASK_MODE_EVENT_TIME_5S)) { ToolEvent* pEvent = (ToolEvent*)m_sysEvents.value(TASK_MODE_EVENT_TIME_5S)->eventTrigger; QCoreApplication::sendEvent(this, pEvent); } } m_nTimerCounter++; } /// /// 等待event触发 /// /// /// void TaskManager::customEvent(QEvent* event) { ToolEvent* pToolEvent = dynamic_cast(event); // 判断事件类型 if (pToolEvent->getExType() == TOOL_EVENT_TYPE::TOOL_TRIGGER) { // 即执行当前工具 VPEnum::RETURN_VALUE ret = ExecuteTool(pToolEvent); pToolEvent->ret = ret; } else if (pToolEvent->getExType() == TOOL_EVENT_TYPE::TASK_TRIGGER) { // 先查找是否有匹配的Task,发送Task触发指令 this->triggerTaskThread(pToolEvent); // 2022-9-4,由于事件还有可能触发Wait工具,还需要和Tool匹配一下 this->triggerToolExecution(pToolEvent); } // Error,不应该走到这里 else { vDebug() << "[Error] Unsupport ToolEvent Type: " << (short)pToolEvent->getExType(); } event->accept(); } /// /// 执行对应的工具 /// /// VPEnum::RETURN_VALUE TaskManager::ExecuteTool(ToolEvent* pToolEvent) { if (pToolEvent == nullptr /*|| m_TaskEvents.size() <= 0*/) { return VPEnum::RETURN_VALUE::None; } //qDebug() << "[EVENT] event[" << pToolEvent->name() << "] activate."; QMap& allPous = g_pPouManager->getAllPous(); // 遍历所有的Pou信息 QMapIterator it(allPous); while (it.hasNext()) { POU* pPou = it.next().value(); //pPou->m_pParentTask = nullptr; if (pPou->pouName() == pToolEvent->groupName()) { TOOL* pTool = pPou->GetToolByName(pToolEvent->name()); if (pTool) { // 在PouManaer中执行本工具 VPEnum::RETURN_VALUE ret = pPou->ToolExecuteStandard(pTool); //qWarning() << "ok"; return ret; } } } return VPEnum::RETURN_VALUE::None; } /// /// 给Task 发送执行指令 /// /// void TaskManager::triggerTaskThread(ToolEvent* pToolEvent) { if (pToolEvent == nullptr || m_EventTasks.size() <= 0) { return; } // 查找本事件是否有对应的Task触发(一个事件可能会对应着多个Task) QList tasks = m_EventTasks.values(pToolEvent->type()); for (TASK* pTask : tasks) { // 如果Task没有处于busy状态, 则通知事件执行 if (pTask->execParams.nStatus != VPEnum::EXEC_STATUS::Busy) { pTask->activator.wakeAll(); } else { // 否则触发失败的次数+1 pTask->execParams.nTriggerFailedCount++; //qWarning() << "[EVENT] Warning: event[" << pToolEvent->name() << "] activate, but task[" << pTask->strName << "] is busy."; } } //qDebug() << "[EVENT] event[" << pToolEvent->name() << "] activate."; //// 查找本事件是否有对应的Task触发(一个事件可能会对应着多个Task) //QList tasks = m_TaskEvents.values(pToolEvent->type()); ////if (tasks.size() > 0) ////{ // for (TASK* pTask : tasks) // { // // 如果Task没有处于busy状态, 则通知事件执行 // if (pTask->execParams.nStatus != VPEnum::EXEC_STATUS::Busy) // { // pTask->activator.wakeAll(); // } // else // { // // 否则触发失败的次数+1 // pTask->execParams.nTriggerFailedCount++; // //qWarning() << "[EVENT] Warning: event[" << pToolEvent->name() << "] activate, but task[" << pTask->strName << "] is busy."; // } // } ////} ////else ////{ // //qWarning() << "[EVENT] Warning: TaskManager:: event[" << pToolEvent->name() << "] activate, but can not find task."; ////} } /// /// 2022-9-4 ToolEvent还可以同时触发Tool执行 /// (目前只有Wait工具可以触发,但是为了以后扩展,这里并没有写死,理论上是所有工具都能触发) /// /// void TaskManager::triggerToolExecution(ToolEvent* pToolEvent) { if (pToolEvent == nullptr || m_EventTools.size() <= 0) { return; } // 查找本事件是否有对应的Task触发(一个事件可能会对应着多个Tool) QList tools = m_EventTools.values(pToolEvent->type()); for (TOOL* pTool : tools) { //// 如果Tool没有处于busy状态, 则触发该工具的通知事件 //if (pTool->execParams.nStatus != VPEnum::EXEC_STATUS::Busy) //{ // 2022-9-25 增加,如果是Wait工具,那么需要判断一下这个Wait工具是否需要等待某一个值来触发,并且判断值是否命中 if (pTool->isWaitTool() && !this->isWaitToolHit(pTool, pToolEvent)) { // 如果没有命中,则跳过此工具触发 continue; } // 如果不是WaitTool,或者是WaitTool并且值命中,则触发该工具的事件 pTool->activator.wakeAll(); // } } } /// /// 处理本轮中涉及到绑定至复杂控件中的变量,包括全局变量、Pou内部变量等(向Runtime触发) /// Reason:在所有Tool执行完一轮之后,需要检查一下Pou的内部变量是否有用做复杂控件的Index的,需要安排触发一下 /// Reason2:每轮Task执行完毕之后,也需要安排触发一下 /// /// void TaskManager::syncComplexIndexToRuntime(QString strGroupName) { GVL* pGVL = g_pGvlManager->getGvl(strGroupName); // 将作为索引的Pou内部变量添加到同步列表中 QList syncComplexIndexes; if (pGVL != nullptr) { const VARIABLES& vars = pGVL->Variables; for (/*const*/ VARIABLE* var : vars) { if (var->bComplexLinkIndex) { syncComplexIndexes.push_back(var); } } } // 2021-12-15 进行复杂控件索引到Runtime的推送 if (syncComplexIndexes.size() > 0) { SyncValueEvent* valueEvent = new SyncValueEvent(); // 携带需要同步的多个接口 valueEvent->setSyncValues(syncComplexIndexes); // post数值同步消息,post内部会自动释放event的指针,无需手工释放 QCoreApplication::postEvent((QObject*)g_pRuntime, valueEvent); } } /// /// 2022-9-25 WaitTool专用,判断Wait工具是否需要等待某一个值,并且这个值是否已经命中 /// /// /// bool TaskManager::isWaitToolHit(TOOL* pTool, ToolEvent* toolEvent) { // 需要从Pou中找到这个Tool对应的Block,参数存在BlockItem里面 POU* pou = g_pPouManager->getPouByName(pTool->strPouName); VALUE* waitValue = pou->getWaitToolValue(pTool); // 检查是否需要等待Value,如果不需要等待,直接返回命中 if (waitValue == nullptr || waitValue->type == VALUE_TYPE::Type_Unknown || waitValue->Ptr == nullptr || toolEvent->m_triggerValue.isNullptr() ) { return true; } vDebug() << "WaitTool : waitValue[" << waitValue->toString() << "]-eventValue[" << toolEvent->m_triggerValue.toString() << "]."; // 如果需要等待Value,那么检测这个Value是否命中,此处用到了重载的== if (*waitValue == toolEvent->m_triggerValue) { return true; } return false; } //============================================================ // // 并行 线程 // //============================================================ /// /// 线程函数 /// void _TaskThread::run() { // 调用函数执行任务 g_pTaskManager->_executeTask(m_pRunningTask); qDebug() << "[TASK][Thread] ThreadPool [" << m_pRunningTask->strName << "] exit."; }