using PTMedicalInsurance.Variables; using RFID; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; namespace PTMedicalInsurance.Business.MetalKeyboard.JustTideEPP { public class MetalKeypadPasswordReaderOld { private int timeouts = 200000; public void OpenKeyboard() { //打开串口 if (JustTideEPPDrv.OpenCom(3, 9600) != 0) { Global.writeLog("打开串口失败"); } else { Global.writeLog("打开串口成功"); } //打开键盘 if (JustTideEPPDrv.EnableKeyboard() != 0) { Global.writeLog("打开键盘失败"); } else { Global.writeLog("打开键盘成功"); } //轮询获取字符并发送到光标处 if (GetAndSendPassword() != 0) { Global.writeLog("获取密码失败"); return; } else { Global.writeLog("获取密码成功"); return; } } public void CloseKeyboard() { //关闭键盘 if (JustTideEPPDrv.DisableKeyboard() != 0) { Global.writeLog("关闭键盘失败"); } else { Global.writeLog("关闭键盘成功"); } //关闭串口 if (JustTideEPPDrv.CloseCom() != 0) { Global.writeLog("关闭串口失败"); } else { Global.writeLog("关闭串口成功"); } } private int GetAndSendPassword() { char key = '\0'; // 使用 Stopwatch 实现超时 var stopwatch = System.Diagnostics.Stopwatch.StartNew(); try { // 主循环:持续轮询,直到超时 while (stopwatch.ElapsedMilliseconds < timeouts) // timeouts 是您的超时毫秒数 { short result = JustTideEPPDrv.PinReportPressed(ref key, 1); // 非阻塞调用 if (result == 0) // 成功读取到按键 { string hexStr = ((int)key).ToString("X2"); // --- 核心:发送字符到焦点窗口 --- if (hexStr != "0D" && hexStr != "1B") // 排除回车和ESC { new SendMsg().SendText(key.ToString()); } else if (hexStr == "0D") // 回车键 '#' { new SendMsg().SendText(key.ToString()); return 0; // 收到确认,成功返回 } else if (hexStr == "1B") // ESC键 { new SendMsg().SendText(key.ToString()); return 0; // 收到取消,也返回成功(或可返回特定码) } } // else: result != 0 表示无按键,继续循环等待 // 关键:同步延迟,避免CPU空转 // 这会在当前线程上阻塞 50ms System.Threading.Thread.Sleep(50); } // 如果走到这里,说明超时了 // 可以选择发送超时信号或直接返回 return -1; // 表示超时 } catch (Exception ex) { // 捕获任何意外异常(虽然 PinReportPressed 可能不会抛出) // 可以记录日志 // Logger.Error($"GetAndSendPassword error: {ex.Message}"); return -99; // 表示未知错误 } finally { stopwatch.Stop(); // 停止计时器 // 如果需要,可以在这里执行清理工作 } } } public class MetalKeypadPasswordReader : IDisposable { private CancellationTokenSource _listenCts; private Task _listenTask; private bool _isListening = false; private const int DEFAULT_TIMEOUT = 30000; // 30秒超时,可根据需要调整 public int timeouts = DEFAULT_TIMEOUT; // 可以让调用方设置超时 /// /// 打开串口和键盘,并启动后台监听(非阻塞) /// public void OpenKeyboard() { if (_isListening) { // 已经在监听,避免重复打开 return; } // 1. 打开串口 if (JustTideEPPDrv.OpenCom(3, 9600) != 0) { Global.writeLog("打开串口失败"); return; } else { Global.writeLog("打开串口成功"); } // 2. 打开键盘 if (JustTideEPPDrv.EnableKeyboard() != 0) { Global.writeLog("打开键盘失败"); JustTideEPPDrv.CloseCom(); // 清理 return; } else { Global.writeLog("打开键盘成功"); } // 3. 启动后台监听任务(关键:非阻塞) _listenCts = new CancellationTokenSource(); _listenTask = Task.Run(() => ListenLoop(_listenCts.Token), _listenCts.Token); _isListening = true; // OpenKeyboard 方法立即返回,不会阻塞! } /// /// 后台监听循环 - 替代原来的 GetAndSendPassword /// private async Task ListenLoop(CancellationToken ct) { char key = '\0'; var stopwatch = System.Diagnostics.Stopwatch.StartNew(); try { while (!ct.IsCancellationRequested && stopwatch.ElapsedMilliseconds < timeouts) { short result = JustTideEPPDrv.PinReportPressed(ref key, 1); if (result == 0) { string hexStr = ((int)key).ToString("X2"); // 发送字符到焦点窗口 if (hexStr != "0D" && hexStr != "1B") { new SendMsg().SendText(key.ToString()); } else if (hexStr == "0D" || hexStr == "1B") // # 或 ESC { new SendMsg().SendText(key.ToString()); // 收到结束键,退出监听循环 break; } } // 非阻塞延迟 await Task.Delay(50, ct); } // 如果是因为超时退出,可以做些处理(可选) if (!ct.IsCancellationRequested && !stopwatch.IsRunning) { // Global.writeLog("键盘监听超时"); } } catch (Exception ex) { // 记录日志 // Logger.Error($"ListenLoop error: {ex.Message}"); } finally { stopwatch.Stop(); } } /// /// 停止监听并关闭硬件 /// public void CloseKeyboard() { if (!_isListening) { return; } // 1. 停止后台监听任务 _listenCts?.Cancel(); try { _listenTask?.Wait(); // 等待监听任务结束 } catch (AggregateException) { /* 忽略取消异常 */ } _listenCts?.Dispose(); _listenCts = null; _listenTask = null; _isListening = false; // 2. 关闭键盘 if (JustTideEPPDrv.DisableKeyboard() != 0) { Global.writeLog("关闭键盘失败"); } else { Global.writeLog("关闭键盘成功"); } // 3. 关闭串口 if (JustTideEPPDrv.CloseCom() != 0) { Global.writeLog("关闭串口失败"); } else { Global.writeLog("关闭串口成功"); } } public void Dispose() { CloseKeyboard(); } } }