WPF C#应用如何持续并行执行notification()方法?
解决WPF应用持续并行检查数据库并显示通知的问题
嘿,我来帮你搞定这个持续检查预约并显示通知的问题!你之前试了线程、计时器但只能单次执行,大概率是因为没做循环、没正确保持计时器引用,或者没处理后台任务的持续执行逻辑。下面给你两个WPF里常用的实用方案:
方案一:用DispatcherTimer(适合UI相关操作)
DispatcherTimer是WPF专门为UI线程设计的计时器,它的Tick事件会在UI线程触发,调用Notification()显示通知时不需要额外处理跨线程问题,非常省心。
public partial class MenuPrincipal : Window { private DispatcherTimer _appointmentCheckTimer; public MenuPrincipal() { InitializeComponent(); // 初始化计时器,设置检查间隔(这里设为30秒,可按需调整) _appointmentCheckTimer = new DispatcherTimer { Interval = TimeSpan.FromSeconds(30) }; // 绑定Tick事件,每次触发就检查预约 _appointmentCheckTimer.Tick += OnCheckAppointments; // 启动计时器 _appointmentCheckTimer.Start(); } private void OnCheckAppointments(object sender, EventArgs e) { // 直接调用你的通知方法 Notification(); } private void Notification() { // 你的原有逻辑:查询数据库检查即将到来的预约 var hasUpcomingAppointments = CheckDatabaseForUpcomingAppointments(); if (hasUpcomingAppointments) { // 显示通知,比如用WPF Toast或自定义弹窗 MessageBox.Show("提醒:有即将到来的预约!"); } } private bool CheckDatabaseForUpcomingAppointments() { // 替换成你的数据库查询逻辑 return true; } protected override void OnClosed(EventArgs e) { base.OnClosed(e); // 窗口关闭时停止计时器,避免内存泄漏 _appointmentCheckTimer?.Stop(); _appointmentCheckTimer = null; } }
方案二:用Task.Run + 循环(适合后台耗时操作)
如果你的数据库查询比较耗时,用DispatcherTimer会卡住UI,这时候推荐用后台任务执行检查,只在需要显示通知时切回UI线程。
public partial class MenuPrincipal : Window { private CancellationTokenSource _cancellationTokenSource; public MenuPrincipal() { InitializeComponent(); // 创建取消令牌,用于窗口关闭时终止后台任务 _cancellationTokenSource = new CancellationTokenSource(); // 启动后台循环任务 Task.Run(async () => await RunAppointmentCheckLoop(_cancellationTokenSource.Token), _cancellationTokenSource.Token); } private async Task RunAppointmentCheckLoop(CancellationToken cancellationToken) { // 无限循环,直到收到取消信号 while (!cancellationToken.IsCancellationRequested) { // 在后台线程执行数据库查询,不卡UI var hasUpcomingAppointments = CheckDatabaseForUpcomingAppointments(); if (hasUpcomingAppointments) { // 切回UI线程显示通知(WPF控件只能在创建它的线程操作) Dispatcher.Invoke(() => Notification()); } // 等待指定间隔,同时响应取消请求 await Task.Delay(TimeSpan.FromSeconds(30), cancellationToken); } } private void Notification() { MessageBox.Show("提醒:有即将到来的预约!"); } private bool CheckDatabaseForUpcomingAppointments() { // 替换成你的数据库查询逻辑 return true; } protected override void OnClosed(EventArgs e) { base.OnClosed(e); // 取消并释放后台任务资源 _cancellationTokenSource?.Cancel(); _cancellationTokenSource?.Dispose(); } }
为什么之前的方案只执行一次?
- 用
Thread时:可能只启动了一次线程,没在内部加循环,执行完Notification()就直接结束了。 - 用
System.Threading.Timer时:这个计时器是弱引用,如果没有保持类级别的引用,会被GC回收,导致只触发一次就停止。 - 缺少持续执行逻辑:不管用哪种方式,都需要循环或重复触发的机制才能实现持续检查。
内容的提问来源于stack exchange,提问作者user9559135
相关产品推荐
相关产品推荐

