簡體   English   中英

System.Timers.Timer 口吃

[英]System.Timers.Timer stutters

在我的 WinUI 3.0 應用程序中,我有一個每秒計數的秒表。 通常,但並非總是如此,它在數數時會結結巴巴。 例如,計時器將在 0:00:04 停留超過一秒,然后跳轉到 0:00:06。

有什么我做錯了嗎?

我的代碼:

public static DateTime startTime;
private readonly System.Timers.Timer timer = new(1000);

public MainPage()
{ 
    ViewModel = App.GetService<MainViewModel>();
    this.InitializeComponent();
    
    timer.AutoReset = true;
    timer.Elapsed += Timer_Tick;
}

private void StartButton_Click(object sender, RoutedEventArgs e)
{
    if (!timer.Enabled)
    {
        startTime = DateTime.Now;
        timer.Start();
    } 
    else
    {
        DateTime stopTime = DateTime.Now;
        timer.Stop();
        timerLabel.Text = "0:00:00";
    }
}

private void Timer_Tick(object sender, EventArgs e)
{
    DispatcherQueue.TryEnqueue(() => 
    { 
        timerLabel.Text = DateTime.Now.Subtract(startTime).ToString(@"h\:mm\:ss"); 
    });

}

一種方法(我為自己解決這個問題的方法)是讓我自己的系統計時器循環以更高分辨率(0.1 秒)觸發,而不是根據計時器滴答更新時鍾顯示,而是使用PropertyChanged事件更新對於Second ,它僅作為PushDT方法的函數出現。 我相信您可以使用這種可靠的每秒一次的事件來編寫替代秒表。

這是我用於我的應用程序的 PC、Android 和 iOS 版本的共享代碼庫,因此我有信心推薦它。 盡管如此,這“只是一種方式”。

static class SystemTimer
{
    static SystemTimer()
    {
        Task.Run(async() => 
        {
            while (!_dispose)
            {
                PushDT(DateTime.Now);
                await Task.Delay(100); 
            }
        });
    }

PushDT基於DateTime.Now更新可綁定的MinuteSecond屬性。

    public static void PushDT(DateTime now)
    {
        // Using a 'now' that doesn't change within this method:
        Second = new DateTime(now.Year, now.Month, now.Day, now.Hour, now.Minute, now.Second, now.Kind);
        Minute = new DateTime(now.Year, now.Month, now.Day, now.Hour, now.Minute, 0, now.Kind);
    }
    public static event PropertyChangedEventHandler PropertyChanged;
    static DateTime _second = DateTime.MinValue;
    public static DateTime Second
    {
        get => _second;
        set
        {
            if(_second != value)
            {
                _second = value;
                PropertyChanged?.Invoke(nameof(SystemTimer), new PropertyChangedEventArgs(nameof(Second)));
            }
        }
    }
}

當(且僅當) Second屬性更改為“新的第二個”時,它會觸發Second的屬性更改,從而更新顯示。 需要注意的一點是,當需要更新 UI 時,需要將事件編組到 UI 線程上,而如何做到這一點取決於平台( SystemTimer類本身是可移植的)。

UI 線程必須承受額外的負擔才能跳過。 我希望這個建議可以幫助你達到你想要的結果。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM