【问题标题】:WPF / C# (No MVVM) Timer with Countdown ClockWPF / C#(无 MVVM)带倒计时时钟的计时器
【发布时间】:2019-12-05 16:51:26
【问题描述】:

大家好, 我正在努力解决编码问题,我需要一些帮助。我的过程需要一个 300 秒(5 分钟)的计时器来触发事件以刷新网格控件。这工作得很好。问题是,我需要向用户倒计时 5 分钟/300 秒,以便他们知道下一次新鲜发生在“X”秒内。目标是倒计时、刷新并向用户显示下一次刷新。

以下所有代码示例都是我尝试过的示例。

我有用于刷新的代码,但在第一次执行后发生了一些奇怪的事情。计时器倒计时到 0,刷新,然后在 300 秒处再次重新启动(好),但每次倒计时都会在其后面闪烁第二个计时器。所以我看到 300, 299, 298, ... 然后又是 300, 299, 298, ...;因此,它看起来像 300、299、298、300、297、299、296、298 等。看着很恶心。更不用说尝试观看 20 分钟了……

我的 300 秒计时器是一个 System.Timers.Timer int eh 下面的示例(提醒,这有效):

public partial class MasterControl
{
private Timer _t;

public MasterControl()
        {
            InitializeComponent();

        }

public void Dispose()
        {
            _t?.Dispose();
            _handle?.Dispose();
        }

        private void Master_OnLoaded(object sender, RoutedEventArgs e)
        {
            var fd = new FillMaster();
            GridMaster.ItemsSource = fd.GridPopulate("TblName", App.UserName);
            _t = new Timer();
            _t.Elapsed += OnTimedEvent;
            _t.Interval = 300000;
            _t.Enabled = true;
        }
        private void OnTimedEvent(object source, ElapsedEventArgs e)
        {
            Dispatcher.Invoke(() =>
            {
                try
                {
                    var fd = new FillMaster();
                    GridMaster.ItemsSource = fd.GridPopulate("TblName", App.UserName);
                }
                catch (SqlException)
                {
                    /*  swallow */
                }
            });
        }
}

我试图做的是添加一个填充标签的倒计时。

我加了

private TimeSpan _time;
private DispatcherTimer _timer;

我将 OnTimedEvent 代码调整为以下示例,但它不起作用。这是它开始在刷新时翻倍的地方。我尝试了 GC 看看这是否可行。没有骰子。

private void OnTimedEvent(object source, ElapsedEventArgs e)
{
    Dispatcher.Invoke(() =>
    {
        try
        {
            var fd = new FillMaster();
            GridMaster.ItemsSource = fd.GridPopulate("IntakeCheckList", App.UserName);
            TbCountDown.Content = "";
            _time = TimeSpan.FromSeconds(60);

            _timer = new DispatcherTimer(new TimeSpan(0, 0, 1), DispatcherPriority.Normal, delegate
            {
                TbCountDown.Content = _time.ToString("c");
                if (_time == TimeSpan.Zero)
                {
                    _timer.Stop();
                    GC.Collect();
                    GC.WaitForPendingFinalizers();
                    GC.Collect();
                }

                _time = _time.Add(TimeSpan.FromSeconds(-1));
            }, Application.Current.Dispatcher);

            _timer.Start();
        }
        catch (SqlException)
        {
            /*  swallow */
        }
    });
}

我还发现了一些导致同样问题的代码。

private void Countdown(int count, TimeSpan interval, Action<int> ts)
        {
            var dt = new DispatcherTimer {Interval = interval};
            dt.Tick += (_, a) =>
            {
                if (count-- == 0)
                    dt.Stop();
                else
                    ts(count);
            };
            ts(count);
            dt.Start();
        }

然后我将以下内容添加到 OnTimedEvent

Countdown(30, TimeSpan.FromSeconds(5), cur => TbCountDown.Content = cur.ToString());

在这里看到

private void OnTimedEvent(object source, ElapsedEventArgs e)
        {
            Dispatcher.Invoke(() =>
            {
                Countdown(30, TimeSpan.FromSeconds(5), cur => TbCountDown.Content = cur.ToString());

                try
                {
                    var fd = new FillMaster();
                    GridMaster.ItemsSource = fd.GridPopulate("IntakeCheckList", App.UserName);
                }
                catch (SqlException)
                {
                    /*  swallow */
                }
            });
        }

这也因完全相同的问题而失败。

最终,有没有办法从 System.Timers.Timer 或您可以帮助我的其他东西中获取倒计时?

谢谢!

【问题讨论】:

    标签: c# wpf timer


    【解决方案1】:

    您实际上只需要一个简单的 DispatcherTimer 和一个循环重置为当前时间 + 300 秒的 DateTime。

    public partial class MainWindow : Window
    {
        private readonly DispatcherTimer timer = new DispatcherTimer();
        private DateTime endTime;
    
        public MainWindow()
        {
            InitializeComponent();
    
            timer.Interval = TimeSpan.FromSeconds(1);
            timer.Tick += new EventHandler(OnTimerTick);
            timer.Start();
        }
    
        private void OnTimerTick(object sender, EventArgs e)
        {
            var now = DateTime.Now;
    
            if (endTime < now)
            {
                endTime = now.AddSeconds(300);
            }
    
            label.Content = (endTime - now).ToString(@"mm\:ss");
        }
    }
    

    【讨论】:

    • 完美运行。我能够将其集成到我的代码中,现在每 5 分钟(或 00:00),系统重置并开始新的倒计时。非常感谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多