using System; using System.Collections.Generic; using System.Linq; using System.Printing; using System.Threading; using System.Threading.Tasks; public class PrintMonitor { public async Task CheckPrintStatusAsync( string printerName, string targetJobName, CancellationToken cancellationToken, TimeSpan? timeout = null) { var timeoutValue = timeout ?? TimeSpan.FromSeconds(60); using (var timeoutCts = new CancellationTokenSource(timeoutValue)) using (var linkedCts = CancellationTokenSource.CreateLinkedTokenSource( cancellationToken, timeoutCts.Token)) { try { while (!linkedCts.IsCancellationRequested) { var isCompleted = await Task.Run(() => { // 关键修改:每个操作线程创建自己的PrintServer using (var printServer = new LocalPrintServer()) { var printQueue = GetPrintQueue(printServer, printerName); return CheckJobs(printQueue, targetJobName); } }, linkedCts.Token); if (isCompleted) return "Success"; await Task.Delay(1000, linkedCts.Token); } } catch (OperationCanceledException ex) { HandleCancellation(timeoutCts, cancellationToken, timeoutValue); throw; } } //throw new OperationCanceledException(); return "Success"; } private PrintQueue GetPrintQueue(LocalPrintServer server, string printerName) { try { return string.IsNullOrEmpty(printerName) ? server.DefaultPrintQueue : server.GetPrintQueue(printerName); } catch (Exception ex) { throw new InvalidOperationException($"获取打印机队列失败: {ex.Message}"); } } private bool CheckJobs(PrintQueue queue, string targetJobName) { queue.Refresh(); var jobs = queue.GetPrintJobInfoCollection() ?? throw new Exception("无法获取打印任务列表"); foreach (PrintSystemJobInfo job in jobs) { if (job.Name.Contains(targetJobName)) { try { CheckJobStatus(job); return job.JobStatus.HasFlag(PrintJobStatus.Completed); } catch (Exception ex) { // 仅传播需要处理的异常 if (!IsExpectedStatus(job.JobStatus)) throw new Exception("关键打印错误", ex); } } } return false; } private bool IsExpectedStatus(PrintJobStatus status) { // 定义可忽略的临时状态 var ignorableStatuses = new[] { PrintJobStatus.Printing, PrintJobStatus.Spooling, PrintJobStatus.Retained }; return ignorableStatuses.Any(s => status.HasFlag(s)); } private void CheckJobStatus(PrintSystemJobInfo job) { // 成功状态直接返回 if (job.JobStatus.HasFlag(PrintJobStatus.Completed)) return; // 状态分类配置 var ignorableStatuses = new[] { PrintJobStatus.Printing, // 正在打印 PrintJobStatus.Retained, // 任务保留 PrintJobStatus.Spooling, // 后台处理 PrintJobStatus.Paused // 用户主动暂停 }; var criticalStatuses = new[] { PrintJobStatus.Error, // 通用错误 PrintJobStatus.PaperOut, // 缺纸 //PrintJobStatus.PaperJam, // 卡纸 PrintJobStatus.Offline // 脱机 }; // 第一步:检查可忽略的中间状态 if (ignorableStatuses.Any(s => job.JobStatus.HasFlag(s))) { return; // 静默继续等待 } // 第二步:检测关键错误状态 var criticalStatus = criticalStatuses.FirstOrDefault(s => job.JobStatus.HasFlag(s)); if (criticalStatus != default) { throw new Exception($"打印错误: {GetStatusDescription(criticalStatus)}"); } // 第三步:处理未知状态 throw new Exception($"无法处理的打印状态: {FormatCompositeStatus(job.JobStatus)}"); } // 辅助方法:获取状态描述 private string GetStatusDescription(PrintJobStatus status) { // 优先处理复合状态 if ((status & (PrintJobStatus.Error | PrintJobStatus.Offline)) != 0) { return "设备故障"; } // 处理单一状态 switch (status) { case PrintJobStatus.PaperOut: return "缺纸"; case PrintJobStatus.Spooling: return "后台处理中"; default: return status.ToString(); } } // 辅助方法:格式化复合状态 private string FormatCompositeStatus(PrintJobStatus status) { var activeFlags = Enum.GetValues(typeof(PrintJobStatus)) .Cast() .Where(s => s != PrintJobStatus.None && status.HasFlag(s)) .Select(s => s.ToString()); return string.Join(" | ", activeFlags); } private void HandleCancellation( CancellationTokenSource timeoutCts, CancellationToken originalToken, TimeSpan timeout) { if (timeoutCts.IsCancellationRequested) throw new TimeoutException($"操作超时 ({timeout.TotalMinutes}分钟)"); if (originalToken.IsCancellationRequested) throw new OperationCanceledException("用户取消操作"); } }