Browse Source

优化打印问题,导致的退出程序变慢。

张洋 1 week ago
parent
commit
f5dbff28f9

+ 97 - 53
zhipuzi_pos_windows/worker/CPosPrinterWorker.cpp

@@ -34,32 +34,34 @@ void CPosPrinterWorker::Start()
 
 	//处理收银打印
 	std::thread(&CPosPrinterWorker::HandleShouyinPrinter, this).detach();
+	CAppEnv::GetInstance()->AddWorkerNum();
 
 	//处理标签打印
 	std::thread(&CPosPrinterWorker::HandleBiaoqianPrinter, this).detach();
+	CAppEnv::GetInstance()->AddWorkerNum();
 
 	//处理厨房打印
 	std::thread(&CPosPrinterWorker::HandleChufangPrinter, this).detach();
+	CAppEnv::GetInstance()->AddWorkerNum();
 }
 
 void CPosPrinterWorker::Stop()
 {
 	m_is_work = false;
 
-	StopShouyinChannels();
+	StopShouyinChannelsForProcessExit();
 }
 
 void CPosPrinterWorker::RefreshShouyinChannels()
 {
 	//设置变更后重建通道。容器锁在 StartShouyinChannels/StopShouyinChannels 内部加,
-	//这里不能持锁(否则与内部加锁自死锁,且会把 join 拖进临界区)
+	StopShouyinChannels();
+
 	StartShouyinChannels();
 }
 
 void CPosPrinterWorker::StartShouyinChannels()
 {
-	StopShouyinChannels();
-
 	std::string printer_leixing = CSetting::GetInstance()->GetParam("setting_printer_leixing");
 
 	//网口不走句柄通道
@@ -76,7 +78,7 @@ void CPosPrinterWorker::StartShouyinChannels()
 		//自动模式:同时检测usb、并口、串口
 		m_usb_devices.clear();
 		int nDevice = GetDevicePath((LPGUID)&USB_GUID, m_usb_devices);
-		LOG_INFO("可用的USB打印机数量:" << nDevice);
+		//LOG_INFO("可用的USB打印机数量:" << nDevice);
 
 		std::string setting_biaoqian_printer_usb = CSetting::GetInstance()->GetParam("setting_biaoqian_printer_usb");
 		std::wstring ws_setting_biaoqian_printer_usb = CLewaimaiString::UTF8ToUnicode(setting_biaoqian_printer_usb);
@@ -137,7 +139,7 @@ void CPosPrinterWorker::StartShouyinChannels()
 		ch->portPath = it->first;
 		ch->portKind = it->second;
 
-		ch->worker = std::thread(&CPosPrinterWorker::ChannelWorker, this, ch);
+		ch->worker = std::thread(&CPosPrinterWorker::ChannelWorker, ch);
 		new_channels.push_back(ch);
 	}
 
@@ -186,6 +188,30 @@ void CPosPrinterWorker::StopShouyinChannels()
 	//channels 出作用域:shared_ptr 归零,端口句柄已由 worker 自身收尾关闭
 }
 
+void CPosPrinterWorker::StopShouyinChannelsForProcessExit()
+{
+	std::vector<std::shared_ptr<CPortSendChannel>> channels;
+	{
+		std::lock_guard<std::mutex> lock(m_shouyin_channels_mutex);
+		channels.swap(m_shouyin_channels);
+	}
+
+	for (std::vector<std::shared_ptr<CPortSendChannel>>::iterator it = channels.begin(); it != channels.end(); it++)
+	{
+		std::lock_guard<std::mutex> lock((*it)->mtx);
+		(*it)->stop = true;
+	}
+
+	//进程最终退出时允许丢弃在途打印,不等待可能被驱动阻塞的端口 I/O
+	for (std::vector<std::shared_ptr<CPortSendChannel>>::iterator it = channels.begin(); it != channels.end(); it++)
+	{
+		if ((*it)->worker.joinable())
+		{
+			(*it)->worker.detach();
+		}
+	}
+}
+
 void CPosPrinterWorker::ChannelWorker(std::shared_ptr<CPortSendChannel> ch)
 {
 	//在通道线程中打开端口,避免驱动响应慢时阻塞 Start 或设置刷新调用
@@ -227,14 +253,20 @@ void CPosPrinterWorker::ChannelWorker(std::shared_ptr<CPortSendChannel> ch)
 		{
 			if (!OpenChannelHandle(ch))
 			{
-				LOG_INFO("端口暂不可用,丢弃本次打印数据,Path = " << ch->portPath.c_str());
+				//LOG_INFO("端口暂不可用,丢弃本次打印数据,Path = " << ch->portPath.c_str());
 				continue;
 			}
 		}
 
 		//同步写出:数据写进驱动缓冲即返回,不做超时等待
 		DWORD dwWrite = 0;
+		ULONGLONG write_started = ::GetTickCount64();
 		BOOL ret = ::WriteFile(ch->hPort, data.c_str(), (DWORD)data.length(), &dwWrite, NULL);
+		ULONGLONG write_elapsed = ::GetTickCount64() - write_started;
+		if (write_elapsed >= 50)
+		{
+			//LOG_INFO("收银打印 WriteFile 耗时:" << write_elapsed << " ms, Path = " << ch->portPath.c_str());
+		}
 		{
 			std::lock_guard<std::mutex> lock(ch->mtx);
 			if (ch->stop)
@@ -246,7 +278,7 @@ void CPosPrinterWorker::ChannelWorker(std::shared_ptr<CPortSendChannel> ch)
 		if (!ret)
 		{
 			//写失败可能是usb热插拔,关闭旧句柄后按路径重开一次再重试
-			LOG_INFO("端口写入失败,尝试重开句柄,hPort:" << ch->hPort << ", Path = " << ch->portPath.c_str());
+			//LOG_INFO("端口写入失败,尝试重开句柄,hPort:" << ch->hPort << ", Path = " << ch->portPath.c_str());
 
 			CloseHandle(ch->hPort);
 			ch->hPort = NULL;
@@ -262,7 +294,13 @@ void CPosPrinterWorker::ChannelWorker(std::shared_ptr<CPortSendChannel> ch)
 				}
 
 				dwWrite = 0;
+				write_started = ::GetTickCount64();
 				ret = ::WriteFile(ch->hPort, data.c_str(), (DWORD)data.length(), &dwWrite, NULL);
+				write_elapsed = ::GetTickCount64() - write_started;
+				if (write_elapsed >= 50)
+				{
+					//LOG_INFO("收银打印重试 WriteFile 耗时:" << write_elapsed << " ms, Path = " << ch->portPath.c_str());
+				}
 				{
 					std::lock_guard<std::mutex> lock(ch->mtx);
 					if (ch->stop)
@@ -275,11 +313,11 @@ void CPosPrinterWorker::ChannelWorker(std::shared_ptr<CPortSendChannel> ch)
 
 		if (!ret || dwWrite != (DWORD)data.length())
 		{
-			LOG_INFO("端口写入失败,hPort:" << ch->hPort << ", dwWrite:" << dwWrite << ", Path = " << ch->portPath.c_str());
+			//LOG_INFO("端口写入失败,hPort:" << ch->hPort << ", dwWrite:" << dwWrite << ", Path = " << ch->portPath.c_str());
 			continue;
 		}
 
-		LOG_INFO("Write Success, hPort:" << ch->hPort << ", dwWrite:" << dwWrite);
+		//LOG_INFO("Write Success, hPort:" << ch->hPort << ", dwWrite:" << dwWrite);
 	}
 
 	if (ch->hPort != NULL)
@@ -310,22 +348,22 @@ bool CPosPrinterWorker::OpenChannelHandle(std::shared_ptr<CPortSendChannel> ch)
 		if (error == 2)
 		{
 			//没有指定的文件
-			LOG_INFO("没有找到对应的端口,Path = " << ch->portPath.c_str());
+			//LOG_INFO("没有找到对应的端口,Path = " << ch->portPath.c_str());
 		}
 		else if (error == 5)
 		{
-			LOG_INFO("端口被占用,Path = " << ch->portPath.c_str());
+			//LOG_INFO("端口被占用,Path = " << ch->portPath.c_str());
 		}
 		else
 		{
-			LOG_INFO("打开端口失败,Path = " << ch->portPath.c_str() << ", error = " << error);
+			//LOG_INFO("打开端口失败,Path = " << ch->portPath.c_str() << ", error = " << error);
 		}
 
 		return false;
 	}
 
 	ch->hPort = hPort;
-	LOG_INFO("打开端口成功,hPort:" << hPort << ", Path = " << ch->portPath.c_str());
+	//LOG_INFO("打开端口成功,hPort:" << hPort << ", Path = " << ch->portPath.c_str());
 
 	return true;
 }
@@ -342,17 +380,17 @@ HANDLE CPosPrinterWorker::OpenComPort(const std::wstring& com_path)
 		if (error == 2)
 		{
 			//没有指定的文件
-			LOG_INFO("没有找到对应的串口 " << com_path.c_str());
+			//LOG_INFO("没有找到对应的串口 " << com_path.c_str());
 		}
 		else if (error == 5)
 		{
-			LOG_INFO("串口被占用 " << com_path.c_str());
+			//LOG_INFO("串口被占用 " << com_path.c_str());
 		}
 
 		return NULL;
 	}
 
-	LOG_INFO(com_path.c_str() << " success, handle:" << hPort);
+	//LOG_INFO(com_path.c_str() << " success, handle:" << hPort);
 
 	//佳博的串口打印机,默认是这个波特率
 	DCB dcb = {};
@@ -362,7 +400,7 @@ HANDLE CPosPrinterWorker::OpenComPort(const std::wstring& com_path)
 
 	if (!SetCommState(hPort, &dcb))
 	{
-		LOG_INFO("set baudRate failed!");
+		//LOG_INFO("set baudRate failed!");
 		CloseHandle(hPort);
 		return NULL;
 	}
@@ -373,7 +411,7 @@ HANDLE CPosPrinterWorker::OpenComPort(const std::wstring& com_path)
 	tmouts.ReadIntervalTimeout = 100;
 	tmouts.ReadTotalTimeoutMultiplier = 100;
 	tmouts.ReadTotalTimeoutConstant = 100;
-	tmouts.WriteTotalTimeoutConstant = 1000;
+	tmouts.WriteTotalTimeoutConstant = 3000;
 	tmouts.WriteTotalTimeoutMultiplier = 0;
 	SetCommTimeouts(hPort, &tmouts);
 
@@ -425,7 +463,7 @@ void CPosPrinterWorker::HandleShouyinPrinter()
 
 		if (data.empty())
 		{
-			Sleep(100);
+			Sleep(50);
 			continue;
 		}
 
@@ -437,6 +475,8 @@ void CPosPrinterWorker::HandleShouyinPrinter()
 			m_shouyin_printer_queue.pop();
 		}
 	}
+
+	CAppEnv::GetInstance()->DelWorkerNum(L"CPosPrinterWorker::HandleShouyinPrinter");
 }
 
 void CPosPrinterWorker::HandleBiaoqianPrinter()
@@ -460,7 +500,7 @@ void CPosPrinterWorker::HandleBiaoqianPrinter()
 
 		if (data.empty())
 		{
-			Sleep(100);
+			Sleep(50);
 			continue;
 		}
 
@@ -472,6 +512,8 @@ void CPosPrinterWorker::HandleBiaoqianPrinter()
 			m_biaoqian_printer_queue.pop();
 		}
 	}
+
+	CAppEnv::GetInstance()->DelWorkerNum(L"CPosPrinterWorker::HandleBiaoqianPrinter");
 }
 
 void CPosPrinterWorker::HandleChufangPrinter()
@@ -493,7 +535,7 @@ void CPosPrinterWorker::HandleChufangPrinter()
 
 		if (!hasData)
 		{
-			Sleep(100);
+			Sleep(50);
 			continue;
 		}
 
@@ -505,6 +547,8 @@ void CPosPrinterWorker::HandleChufangPrinter()
 			m_chufang_printer_queue.pop();
 		}
 	}
+
+	CAppEnv::GetInstance()->DelWorkerNum(L"CPosPrinterWorker::HandleChufangPrinter");
 }
 
 void CPosPrinterWorker::SendDataToShouyinPirnter(std::string data)
@@ -534,7 +578,7 @@ void CPosPrinterWorker::SendDataToShouyinPirnter(std::string data)
 		catch (std::exception& e)
 		{
 			std::string err = e.what();
-			LOG_INFO("网口打印机连接失败,IP地址:" << wangkou_ip.c_str() << ",错误信息:" << err.c_str());
+			//LOG_INFO("网口打印机连接失败,IP地址:" << wangkou_ip.c_str() << ",错误信息:" << err.c_str());
 
 			MessageBoxW(NULL, (L"小票网口打印机连接失败,IP地址:" + CLewaimaiString::UTF8ToUnicode(wangkou_ip)).c_str(), L"打印机连接失败", MB_OK);
 			return;
@@ -565,7 +609,7 @@ void CPosPrinterWorker::SendDataToShouyinPirnter(std::string data)
 		}
 		catch (const std::exception& e)
 		{
-			LOG_INFO("网口打印机发送消息失败,错误信息:" << e.what());
+			//LOG_INFO("网口打印机发送消息失败,错误信息:" << e.what());
 		}
 	}
 
@@ -614,7 +658,7 @@ void CPosPrinterWorker::SendDataToBiaoqianPirnter(std::string data)
 		catch (std::exception& e)
 		{
 			std::string err = e.what();
-			LOG_INFO("网口打印机连接失败,IP地址:" << wangkou_ip.c_str() << ",错误信息:" << err.c_str());
+			//LOG_INFO("网口打印机连接失败,IP地址:" << wangkou_ip.c_str() << ",错误信息:" << err.c_str());
 
 			MessageBoxW(NULL, (L"标签网口打印机连接失败,IP地址:" + CLewaimaiString::UTF8ToUnicode(wangkou_ip)).c_str(), L"打印机连接失败", MB_OK);
 			return;
@@ -634,7 +678,7 @@ void CPosPrinterWorker::SendDataToBiaoqianPirnter(std::string data)
 			bool ret = WriteWithTimeout(hPort, data.c_str(), (DWORD)data.length(), 5000, dwWrite);
 			if (!ret || dwWrite != (DWORD)data.length())
 			{
-				LOG_INFO("WriteWithTimeout Failed or partial write!, hPort:" << hPort << ", dwWrite:" << dwWrite);
+				//LOG_INFO("WriteWithTimeout Failed or partial write!, hPort:" << hPort << ", dwWrite:" << dwWrite);
 				continue;
 			}
 		}
@@ -648,7 +692,7 @@ void CPosPrinterWorker::SendDataToBiaoqianPirnter(std::string data)
 		}
 		catch (const std::exception& e)
 		{
-			LOG_INFO("网口打印机发送消息失败,错误信息:" << e.what());
+			//LOG_INFO("网口打印机发送消息失败,错误信息:" << e.what());
 		}
 	}
 
@@ -686,7 +730,7 @@ void CPosPrinterWorker::SendDataToChufangPirnter(ChufangPrinterContent chufang_d
 	catch (std::exception& e)
 	{
 		std::string err = e.what();
-		LOG_INFO("厨房网口打印机连接失败,IP地址:" << ip.c_str() << ",错误信息:" << err.c_str());
+		//LOG_INFO("厨房网口打印机连接失败,IP地址:" << ip.c_str() << ",错误信息:" << err.c_str());
 
 		MessageBoxW(NULL, (L"厨房网口打印机连接失败,IP地址:" + CLewaimaiString::UTF8ToUnicode(ip)).c_str(), L"打印机连接失败", MB_OK);
 		return;
@@ -699,7 +743,7 @@ void CPosPrinterWorker::SendDataToChufangPirnter(ChufangPrinterContent chufang_d
 	}
 	catch (const std::exception& e)
 	{
-		LOG_INFO("网口打印机发送消息失败,错误信息:" << e.what());
+		//LOG_INFO("网口打印机发送消息失败,错误信息:" << e.what());
 	}
 
 	m_socket.close();
@@ -714,7 +758,7 @@ void CPosPrinterWorker::InitUsb()
 	//取设备路径
 	m_usb_devices.clear();
 	int nDevice = GetDevicePath((LPGUID)&USB_GUID, m_usb_devices);
-	LOG_INFO("可用的USB打印机数量:" << nDevice);
+	//LOG_INFO("可用的USB打印机数量:" << nDevice);
 
 	//添加usb端口
 	int i = 0;
@@ -731,13 +775,13 @@ void CPosPrinterWorker::InitUsb()
 			continue;
 		}
 
-		LOG_INFO("准备打开端口 Port = " << m_usb_devices[i].c_str());
+		//LOG_INFO("准备打开端口 Port = " << m_usb_devices[i].c_str());
 
 		HANDLE hPort = CreateFile(m_usb_devices[i].c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);
 
 		if (hPort == INVALID_HANDLE_VALUE)
 		{
-			LOG_INFO("打开USB端口失败, Port = " << m_usb_devices[i].c_str());
+			//LOG_INFO("打开USB端口失败, Port = " << m_usb_devices[i].c_str());
 
 			// 打开端口失败
 			DWORD error = GetLastError();
@@ -745,18 +789,18 @@ void CPosPrinterWorker::InitUsb()
 			if (error == 2)
 			{
 				//没有指定的文件
-				LOG_INFO("没有找对对应的usb端口");
+				//LOG_INFO("没有找对对应的usb端口");
 			}
 			else if (error == 5)
 			{
-				LOG_INFO("usb端口被占用!");
+				//LOG_INFO("usb端口被占用!");
 			}
 
 			i++;
 			continue;
 		}
 
-		LOG_INFO("打开usb端口成功,准备进行打印机检测! hPort:" << hPort);
+		//LOG_INFO("打开usb端口成功,准备进行打印机检测! hPort:" << hPort);
 
 		m_hShouyinPorts.push_back(hPort);
 
@@ -778,7 +822,7 @@ bool CPosPrinterWorker::InitOneUsb(std::wstring usb_path, int nType)
 
 	if (hPort == INVALID_HANDLE_VALUE)
 	{
-		LOG_INFO("打开USB端口失败, Port = " << usb_path.c_str());
+		//LOG_INFO("打开USB端口失败, Port = " << usb_path.c_str());
 
 		// 打开端口失败
 		DWORD error = GetLastError();
@@ -786,17 +830,17 @@ bool CPosPrinterWorker::InitOneUsb(std::wstring usb_path, int nType)
 		if (error == 2)
 		{
 			//没有指定的文件
-			LOG_INFO("没有找对对应的usb端口");
+			//LOG_INFO("没有找对对应的usb端口");
 		}
 		else if (error == 5)
 		{
-			LOG_INFO("usb端口被占用!");
+			//LOG_INFO("usb端口被占用!");
 		}
 
 		return false;
 	}
 
-	LOG_INFO("打开usb端口,准备进行打印机检测! hPort:" << hPort);
+	//LOG_INFO("打开usb端口,准备进行打印机检测! hPort:" << hPort);
 
 	if (nType == 1)
 	{
@@ -818,18 +862,18 @@ bool CPosPrinterWorker::InitBingkou()
 
 	if (hPort == INVALID_HANDLE_VALUE)
 	{
-		LOG_INFO("打开并口失败, Port = " << LptStr.c_str());
+		//LOG_INFO("打开并口失败, Port = " << LptStr.c_str());
 
 		DWORD error = GetLastError();
 
 		if (error == 2)
 		{
 			//没有指定的文件
-			LOG_INFO("本机器没有并口!");
+			//LOG_INFO("本机器没有并口!");
 		}
 		else if (error == 5)
 		{
-			LOG_INFO("并口被占用!");
+			//LOG_INFO("并口被占用!");
 		}
 
 		return false;
@@ -837,7 +881,7 @@ bool CPosPrinterWorker::InitBingkou()
 	else
 	{
 		//这个表示并口可以使用
-		LOG_INFO("找到并口,准备进行打印机检测! hPort:" << hPort);
+		//LOG_INFO("找到并口,准备进行打印机检测! hPort:" << hPort);
 
 		m_hShouyinPorts.push_back(hPort);
 	}
@@ -877,7 +921,7 @@ int CPosPrinterWorker::GetDevicePath(LPGUID lpGuid, std::vector<std::wstring>& u
 	HDEVINFO hDevInfoSet = ::SetupDiGetClassDevs(lpGuid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
 	if (hDevInfoSet == INVALID_HANDLE_VALUE)
 	{
-		LOG_INFO("SetupDiGetClassDevs failed");
+		//LOG_INFO("SetupDiGetClassDevs failed");
 		return 0;
 	}
 
@@ -885,7 +929,7 @@ int CPosPrinterWorker::GetDevicePath(LPGUID lpGuid, std::vector<std::wstring>& u
 	PSP_DEVICE_INTERFACE_DETAIL_DATA pDetail = (PSP_DEVICE_INTERFACE_DETAIL_DATA)::GlobalAlloc(LMEM_ZEROINIT, INTERFACE_DETAIL_SIZE);
 	if (pDetail == NULL)
 	{
-		LOG_INFO("GlobalAlloc pDetail failed");
+		//LOG_INFO("GlobalAlloc pDetail failed");
 		::SetupDiDestroyDeviceInfoList(hDevInfoSet);
 		return 0;
 	}
@@ -960,14 +1004,14 @@ int CPosPrinterWorker::GetDevicePath(LPGUID lpGuid, std::vector<std::wstring>& u
 			}
 			if (got)
 			{
-				LOG_INFO(L"BusReportedDeviceDesc: " << busReported);
+				//LOG_INFO(L"BusReportedDeviceDesc: " << busReported);
 			}
 		}
 
 		// 如果既不是通用打印类也没有 busReported 描述,跳过该设备
 		if (regName != strUSBPrint && regName != strUSBPrint_EN && busReported.empty())
 		{
-			LOG_INFO(L"not good usb, regName:" << regName);
+			//LOG_INFO(L"not good usb, regName:" << regName);
 			continue;
 		}
 
@@ -975,14 +1019,14 @@ int CPosPrinterWorker::GetDevicePath(LPGUID lpGuid, std::vector<std::wstring>& u
 		ifData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
 		if (!::SetupDiEnumDeviceInterfaces(hDevInfoSet, NULL, lpGuid, idx, &ifData))
 		{
-			LOG_INFO("SetupDiEnumDeviceInterfaces failed for idx=" << idx);
+			//LOG_INFO("SetupDiEnumDeviceInterfaces failed for idx=" << idx);
 			continue;
 		}
 
 		// 取得接口细节(包含 DevicePath)
 		if (!SetupDiGetInterfaceDeviceDetail(hDevInfoSet, &ifData, pDetail, INTERFACE_DETAIL_SIZE, NULL, NULL))
 		{
-			LOG_INFO("SetupDiGetInterfaceDeviceDetail failed for idx=" << idx);
+			//LOG_INFO("SetupDiGetInterfaceDeviceDetail failed for idx=" << idx);
 			continue;
 		}
 
@@ -995,22 +1039,22 @@ int CPosPrinterWorker::GetDevicePath(LPGUID lpGuid, std::vector<std::wstring>& u
 		size_t posPid = DevicePath.find(L"pid_");
 		if (posVid != std::wstring::npos && posVid + 4 + 4 <= DevicePath.length()) vid = DevicePath.substr(posVid + 4, 4);
 		if (posPid != std::wstring::npos && posPid + 4 + 4 <= DevicePath.length()) pid = DevicePath.substr(posPid + 4, 4);
-		LOG_INFO("Vid:" << vid.c_str() << ", Pid:" << pid.c_str());
+		//LOG_INFO("Vid:" << vid.c_str() << ", Pid:" << pid.c_str());
 
 		// 输出检测到的名称(优先 busReported,其次注册表名)
 		if (!busReported.empty())
 		{
-			LOG_INFO(L"Detected printer name: " << busReported);
+			//LOG_INFO(L"Detected printer name: " << busReported);
 		}
 		else
 		{
-			LOG_INFO(L"Detected registry name: " << regName);
+			//LOG_INFO(L"Detected registry name: " << regName);
 		}
 
 		// 将 DevicePath 添加到结果集合
 		usb_devices.push_back(DevicePath);
 		++nCount;
-		LOG_INFO("Cnt = " << nCount << ", pDetail->DevicePath =" << pDetail->DevicePath);
+		//LOG_INFO("Cnt = " << nCount << ", pDetail->DevicePath =" << pDetail->DevicePath);
 	}
 
 	// 清理并返回

+ 4 - 3
zhipuzi_pos_windows/worker/CPosPrinterWorker.h

@@ -88,11 +88,12 @@ private:
 	//通道的建立与销毁,在Start和设置变更时调用,不再每张票都开关端口
 	void StartShouyinChannels();
 	void StopShouyinChannels();
-	void ChannelWorker(std::shared_ptr<CPortSendChannel> ch);
+	void StopShouyinChannelsForProcessExit();
+	static void ChannelWorker(std::shared_ptr<CPortSendChannel> ch);
 
 	//串口/并口/USB各自的句柄打开与配置,复用于通道建立与热插拔重开
-	HANDLE OpenComPort(const std::wstring& com_path);
-	bool OpenChannelHandle(std::shared_ptr<CPortSendChannel> ch);
+	static HANDLE OpenComPort(const std::wstring& com_path);
+	static bool OpenChannelHandle(std::shared_ptr<CPortSendChannel> ch);
 
 private:
 	std::queue<std::string> m_shouyin_printer_queue;