|
|
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<string> 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<PrintJobStatus>() .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("用户取消操作"); }}
|