Procházet zdrojové kódy

修复退出很慢的问题

张洋 před 1 týdnem
rodič
revize
2f6847d7c7

+ 31 - 3
zhipuzi_pos_windows/helper/CLewaimaiLog.h

@@ -32,16 +32,44 @@ public:
 	//把消息输出到调试控制台(unicode版本)
 	static void OutputDebugMessage(const std::wstring& message)
 	{
+		SYSTEMTIME st{};
+		::GetLocalTime(&st);
+
+		wchar_t timeBuf[32] = { 0 };
+		swprintf_s(
+			timeBuf,
+			L"%04d-%02d-%02d %02d:%02d:%02d.%03d",
+			st.wYear, st.wMonth, st.wDay,
+			st.wHour, st.wMinute, st.wSecond, st.wMilliseconds
+		);
+
 		std::wostringstream __oss;
-		__oss << L"[" << __func__ << L"]@" << __FILE__ << L":" << __LINE__ << L": " << message << L"\r\n";
+		__oss << L"[" << timeBuf << L"] "
+			<< L"[" << __func__ << L"]@" << __FILE__ << L":" << __LINE__
+			<< L": " << message << L"\r\n";
+
 		::OutputDebugStringW(__oss.str().c_str());
 	}
 
 	//把消息输出到调试控制台(ansi版本)
 	static void OutputDebugMessage(const std::string& message)
 	{
+		SYSTEMTIME st{};
+		::GetLocalTime(&st);
+
+		char timeBuf[32] = { 0 };
+		sprintf_s(
+			timeBuf,
+			"%04d-%02d-%02d %02d:%02d:%02d.%03d",
+			st.wYear, st.wMonth, st.wDay,
+			st.wHour, st.wMinute, st.wSecond, st.wMilliseconds
+		);
+
 		std::ostringstream __oss;
-		__oss << "[" << __func__ << "]@" << __FILE__ << ":" << __LINE__ << ": " << message << "\r\n";
+		__oss << "[" << timeBuf << "] "
+			<< "[" << __func__ << "]@" << __FILE__ << ":" << __LINE__
+			<< ": " << message << "\r\n";
+
 		::OutputDebugStringA(__oss.str().c_str());
 	}
 
@@ -77,7 +105,7 @@ public:
 
 		va_end(args);
 
-		::OutputDebugStringW(buffer);
+		CLewaimaiLog::OutputDebugMessage(buffer);
 	}
 
 	//把消息输出到消息框(unicode版本)

+ 1 - 1
zhipuzi_pos_windows/page/CAIxuexiPageUI.cpp

@@ -520,7 +520,7 @@ void CAIxuexiPageUI::HandleUpdateVideo()
 		Sleep(1000 / 30);
 	}
 
-	CAppEnv::GetInstance()->DelWorkerNum();
+	CAppEnv::GetInstance()->DelWorkerNum(L"CAIxuexiPageUI::HandleUpdateVideo");
 }
 
 void CAIxuexiPageUI::UpdateVideoShow()

+ 1 - 1
zhipuzi_pos_windows/page/CSettingPageUI.cpp

@@ -3531,7 +3531,7 @@ void CSettingPageUI::HandleUpdateVideo()
 		Sleep(1000 / 20);
 	}
 
-	CAppEnv::GetInstance()->DelWorkerNum();
+	CAppEnv::GetInstance()->DelWorkerNum(L"CSettingPageUI::HandleUpdateVideo");
 }
 
 void CSettingPageUI::UpdateVideoShow()

+ 2 - 2
zhipuzi_pos_windows/tool/CAppEnv.cpp

@@ -90,7 +90,7 @@ void CAppEnv::AddWorkerNum()
 	m_worker_count++;
 }
 
-void CAppEnv::DelWorkerNum()
+void CAppEnv::DelWorkerNum(std::wstring workerName)
 {
 	std::lock_guard<std::mutex> lock(m_mutex);
 	m_worker_count--;
@@ -98,7 +98,7 @@ void CAppEnv::DelWorkerNum()
 	if (m_worker_count == 0)
 	{
 		//最后一个线程退出了,看看是哪个线程这么慢
-		CLewaimaiLog::OutputDebugMessage(L"最后一个线程退出了,剩余线程数:" + std::to_wstring(m_worker_count));
+		CLewaimaiLog::OutputDebugMessage(L"最后一个线程退出了,剩余线程数:" + std::to_wstring(m_worker_count) + L",线程名称:" + workerName);
 	}
 }
 

+ 1 - 1
zhipuzi_pos_windows/tool/CAppEnv.h

@@ -18,7 +18,7 @@ public:
 	void Stop();
 
 	void AddWorkerNum();
-	void DelWorkerNum();
+	void DelWorkerNum(std::wstring workerName = L"");
 
 	// 异步初始化,避免阻塞主线程
 	void AsyncInit();

+ 1 - 1
zhipuzi_pos_windows/worker/CChengzhongWorker.cpp

@@ -266,7 +266,7 @@ void CChengzhongWorker::HandleWork()
 		this->UpdateShow(new_weight);
 	}
 
-	CAppEnv::GetInstance()->DelWorkerNum();
+	CAppEnv::GetInstance()->DelWorkerNum(L"CChengzhongWorker::HandleWork");
 }
 
 void CChengzhongWorker::RestartSerial()

+ 1 - 1
zhipuzi_pos_windows/worker/CCommonWorker.cpp

@@ -59,5 +59,5 @@ void CCommonWorker::HandleConfirm()
 		newOrder.ConfirmeOrder(order_id);
 	}
 
-	CAppEnv::GetInstance()->DelWorkerNum();
+	CAppEnv::GetInstance()->DelWorkerNum(L"CCommonWorker::HandleConfirm");
 }

+ 2 - 2
zhipuzi_pos_windows/worker/CDiandanAIShibieWorker.cpp

@@ -201,7 +201,7 @@ void CDiandanAIShibieWorker::HandleDiandanAIShibie()
 	}
 
 	//走到这里说明线程要退出了,做一些清理工作
-	CAppEnv::GetInstance()->DelWorkerNum();
+	CAppEnv::GetInstance()->DelWorkerNum(L"CDiandanAIShibieWorker::HandleDiandanAIShibie");
 }
 
 void CDiandanAIShibieWorker::HandleDiandanAIShibieQueue()
@@ -229,5 +229,5 @@ void CDiandanAIShibieWorker::HandleDiandanAIShibieQueue()
 	}
 
 	//走到这里说明线程要退出了,做一些清理工作
-	CAppEnv::GetInstance()->DelWorkerNum();
+	CAppEnv::GetInstance()->DelWorkerNum(L"CDiandanAIShibieWorker::HandleDiandanAIShibieQueue");
 }

+ 33 - 12
zhipuzi_pos_windows/worker/CMqttClientWorker.cpp

@@ -21,6 +21,8 @@ CMqttClientWorker::CMqttClientWorker()
 CMqttClientWorker::~CMqttClientWorker()
 {
 	m_is_closing = true;
+	m_is_running = false;
+	m_stopCv.notify_all();
 	m_async_client.reset();
 }
 
@@ -38,6 +40,7 @@ void CMqttClientWorker::Stop()
 {
 	m_is_closing = true;
 	m_is_running = false;
+	m_stopCv.notify_all();
 }
 
 void CMqttClientWorker::Run()
@@ -75,36 +78,42 @@ void CMqttClientWorker::Run()
 		return;
 	}
 
-	while (m_is_running)
+	while (m_is_running && !m_is_closing)
 	{
-		//一直循环,一直工作,等待接收消息
-		Sleep(100);
+		std::unique_lock<std::mutex> lock(m_stopMutex);
+		m_stopCv.wait_for(lock, std::chrono::milliseconds(100), [this]()
+			{
+				return !m_is_running || m_is_closing;
+			});
 	}
 
+	CLewaimaiLog::OutputDebugMessage("准备退出");
+
 	//准备退出,禁止回调里继续重连/处理
 	m_is_closing = true;
+	m_stopCv.notify_all();
 
 	try
 	{
-		LOG_INFO("Disconnecting from the MQTT server...");
+		CLewaimaiLog::OutputDebugMessage("Disconnecting from the MQTT server...");
 
 		auto client = m_async_client;
 		if (client && client->is_connected())
 		{
 			auto tok = client->disconnect();
 
-			if (!tok->wait_for(std::chrono::seconds(2)))
+			if (!tok->wait_for(std::chrono::milliseconds(200)))
 			{
-				LOG_INFO("MQTT disconnect timeout, wait for pending callbacks to finish.");
+				CLewaimaiLog::OutputDebugMessage("MQTT disconnect timeout, wait for pending callbacks to finish.");
 			}
 			else
 			{
-				LOG_INFO("MQTT disconnected.");
+				CLewaimaiLog::OutputDebugMessage("MQTT disconnected.");
 			}
 		}
 		else
 		{
-			LOG_INFO("MQTT client is already disconnected.");
+			CLewaimaiLog::OutputDebugMessage("MQTT client is already disconnected.");
 		}
 	}
 	catch (const mqtt::exception& exc)
@@ -112,7 +121,7 @@ void CMqttClientWorker::Run()
 		// is_connected() 与 disconnect() 之间连接仍可能被远端断开。
 		if (exc.get_return_code() == MQTTASYNC_DISCONNECTED)
 		{
-			LOG_INFO("MQTT client was already disconnected.");
+			CLewaimaiLog::OutputDebugMessage("MQTT client was already disconnected.");
 		}
 		else
 		{
@@ -121,15 +130,18 @@ void CMqttClientWorker::Run()
 				std::to_string(exc.get_return_code()) +
 				"]: " + exc.get_message();
 
-			LOG_INFO(msg.c_str());
 			CLewaimaiLog::OutputDebugMessage(msg.c_str());
 		}
 	}
 
+	CLewaimaiLog::OutputDebugMessage("MQTT client cleanup complete.");
+
 	//不要 delete,改成释放智能指针
 	m_async_client.reset();
 
-	CAppEnv::GetInstance()->DelWorkerNum();
+	CLewaimaiLog::OutputDebugMessage("MQTT client worker thread exiting.");
+
+	CAppEnv::GetInstance()->DelWorkerNum(L"CMqttClientWorker::Run");
 
 	return;
 }
@@ -144,7 +156,16 @@ void CMqttClientWorker::reconnect()
 		return;
 
 	//暂停10秒后重连
-	std::this_thread::sleep_for(std::chrono::milliseconds(10000));
+	{
+		std::unique_lock<std::mutex> lock(m_stopMutex);
+		if (m_stopCv.wait_for(lock, std::chrono::milliseconds(10000), [this]()
+			{
+				return m_is_closing.load();
+			}))
+		{
+			return;
+		}
+	}
 
 	if (m_is_closing)
 		return;

+ 4 - 0
zhipuzi_pos_windows/worker/CMqttClientWorker.h

@@ -42,6 +42,10 @@ private:
 	//正在退出/关闭,禁止重连和回调继续处理
 	std::atomic_bool m_is_closing{ false };
 
+	// 用于中断 sleep/wait
+	std::mutex m_stopMutex;
+	std::condition_variable m_stopCv;
+
     HWND m_hwnd;
 
 public:

+ 2 - 2
zhipuzi_pos_windows/worker/CVoiceWorker.cpp

@@ -108,7 +108,7 @@ void CVoiceWorker::HandleVoice()
 		//CSystem::my_sleep(8);
 	}
 
-	CAppEnv::GetInstance()->DelWorkerNum();
+	CAppEnv::GetInstance()->DelWorkerNum(L"CVoiceWorker::HandleVoice");
 }
 
 //处理文字转语音的
@@ -137,5 +137,5 @@ void CVoiceWorker::HandleVoiceContent()
 		CSpeech::MSSSpeak(ws_content.c_str());
 	}
 
-	CAppEnv::GetInstance()->DelWorkerNum();
+	CAppEnv::GetInstance()->DelWorkerNum(L"CVoiceWorker::HandleVoiceContent");
 }