You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 04:28:04