使用 System.Timers.Timer 的线程中的倒数计时器

Countdown timer in a thread using System.Timers.Timer

我需要在主 UI 线程之外的另一个线程中 运行 一个倒数计时器。因此我不能使用 DispatcherTimer,因为它只存在于主线程中。因此,我需要一些帮助 System.Timers.Timer - 我找不到任何关于如何在网络上创建倒数计时器的好例子..

这是我目前得到的:

Private void CountdownThread()
{
    // Calculate the total running time
    int runningTime = time.Sum(x => Convert.ToInt32(x));

    // Convert to seconds
    int totalRunningTime = runningTime * 60;

    // New timer
    System.Timers.Timer t = new System.Timers.Timer(1000);
    t.Elapsed += (object sender, System.Timers.ElapsedEventArgs e) => totalRunningTime--;

    // Update the label in the GUI
    lblRunning.Dispatcher.BeginInvoke((Action)(() => {lblRunning.Content = totalRunningTime.ToString(@"hh\:mm\:ss");}));
}        

标签lblRunning显示倒计时值。

编辑:问题是我不知道如何在单独的线程中制作倒数计时器并从该线程更新标签!

您需要 Start() 计时器和 update/invalidate UI 每个滴答:

private void CountdownThread() {
    // Calculate the total running time
    int runningTime = time.Sum(x => Convert.ToInt32(x));

    // Convert to seconds
    int totalRunningTime = runningTime * 60;

    // New timer
    System.Timers.Timer t = new System.Timers.Timer(1000);
    t.Elapsed += (s, e) => {
        totalRunningTime--;
        // Update the label in the GUI
        lblRunning.Dispatcher.BeginInvoke((Action)(() => {
            lblRunning.Content = TimeSpan.FromSeconds(totalRunningTime).ToString();
        }));
    };
    // Start the timer!
    t.Start();
}   

当使用 System.Threading.Tasks 安排主 UI 线程上的工作时,主 UI 线程不会被阻塞。可以在按钮单击事件上使用 async 关键字并执行一些预定工作,例如保存到数据库。当按钮点击事件保存到数据库时,用户仍然可以使用 UI 并进行其他操作。

重组:使用任务不会阻塞 UI 线程;那只是安排 owrk 在一段时间内完成。在这段时间内它没有消耗任何线程的时间——UI 线程和任何其他线程都没有。

所以,实际上可以使用 DispatcherTimer 而不是 System.Timers.Timer 命名空间,因为既不需要新线程也不会阻塞任何线程。

使用 DispatcherTime 的倒数计时器示例代码如下所示:

namespace CountdownTimer
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
   public partial class MainWindow : Window
   {
       TimeSpan runningTime;

       DispatcherTimer dt;

       public MainWindow()
       {
           InitializeComponent();

           // Fill in number of seconds to be countdown from
           runningTime = TimeSpan.FromSeconds(21600);

           dt = new DispatcherTimer(new TimeSpan(0, 0, 1), DispatcherPriority.Normal, delegate
           {
                lblTime.Content = runningTime.ToString(@"hh\:mm\:ss");
                if (runningTime == TimeSpan.Zero) dt.Stop();
                runningTime = runningTime.Add(TimeSpan.FromSeconds(-1));
           }, Application.Current.Dispatcher);

           dt.Start();
       }
   }
}