C#队列管理系统:实现静态表单实时显示更新叫号数据
队列管理系统实时显示解决方案
核心解决思路
- 单例模式保证显示表单唯一:禁止外部直接实例化
FrmDisplay,通过静态方法获取唯一实例,彻底解决重复创建问题。 - 事件驱动实现解耦更新:用全局事件类分离工作站叫号逻辑与显示逻辑,工作站只负责发布更新事件,显示表单自动响应刷新。
- 优化数据存储结构:用字典替代多个独立静态变量,适配更多工作站且维护成本更低。
代码实现
1. 单例模式改造FrmDisplay
public partial class FrmDisplay : Form { private static FrmDisplay _instance; private static readonly object _lockObj = new object(); // 私有构造函数,禁止外部直接实例化 private FrmDisplay() { InitializeComponent(); // 订阅叫号更新事件 QueueDataManager.TicketUpdated += OnTicketUpdated; } // 获取唯一实例的线程安全方法 public static FrmDisplay GetInstance() { lock (_lockObj) { if (_instance == null || _instance.IsDisposed) { _instance = new FrmDisplay(); } return _instance; } } // 处理叫号更新事件,跨线程刷新UI private void OnTicketUpdated(string workstationName, string ticketNumber) { if (InvokeRequired) { Invoke(new Action<string, string>(OnTicketUpdated), workstationName, ticketNumber); return; } // 根据工作站名称更新对应控件,示例用switch适配多个工作站 switch (workstationName) { case "Ght1": lblGht1.Text = ticketNumber; break; case "Ght2": lblGht2.Text = ticketNumber; break; case "Ght3": lblGht3.Text = ticketNumber; break; case "Ght4": lblGht4.Text = ticketNumber; break; case "Ght5": lblGht5.Text = ticketNumber; break; } } }
2. 全局队列数据管理类(事件驱动)
public static class QueueDataManager { // 存储各工作站当前叫号,支持动态新增工作站 public static Dictionary<string, string> CurrentTickets { get; } = new Dictionary<string, string>(); // 叫号更新事件,所有订阅者会收到通知 public static event Action<string, string> TicketUpdated; // 对外暴露的叫号更新方法 public static void UpdateTicket(string workstationName, string ticketNumber) { if (CurrentTickets.ContainsKey(workstationName)) { CurrentTickets[workstationName] = ticketNumber; } else { CurrentTickets.Add(workstationName, ticketNumber); } // 触发事件,通知所有订阅者(比如FrmDisplay) TicketUpdated?.Invoke(workstationName, ticketNumber); } }
3. 工作站表单叫号按钮逻辑改造
private void btnCallTicket_Click(object sender, EventArgs e) { string ticketNumber = lblNumApl.Text; string workstationName = lblSessionpostetravail.Text; // 执行语音合成 var speechSynthesizer = new SpeechSynthesizer(); speechSynthesizer.SpeakAsync($"Ticket numéro {ticketNumber}, {workstationName}"); // 发布叫号更新事件,自动同步到显示表单 QueueDataManager.UpdateTicket(workstationName, ticketNumber); // 确保显示表单处于可见状态 var displayForm = FrmDisplay.GetInstance(); if (!displayForm.Visible) { displayForm.Show(); } else { displayForm.BringToFront(); } }
关键注意事项
- 跨线程UI更新:
SpeakAsync是异步操作,事件可能在非UI线程触发,必须用Invoke确保UI更新在主线程执行,避免异常。 - 扩展性:新增工作站时,只需在
FrmDisplay的switch中添加对应分支,或直接用控件名称与工作站名称绑定的方式(比如控件命名为lbl_工作站名,通过反射直接查找控件),无需修改其他逻辑。 - 资源释放:如果需要关闭
FrmDisplay,建议改为隐藏(Hide()),避免实例被销毁后下次需要重新创建。
内容的提问来源于stack exchange,提问作者Eloge28
相关产品推荐
相关产品推荐

