【问题标题】:Countdown timer in a thread using System.Timers.Timer使用 System.Timers.Timer 的线程中的倒数计时器
【发布时间】:2015-06-11 15:43:07
【问题描述】:

我需要在主 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 显示倒计时值。

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

【问题讨论】:

  • 你说不能用主线程,为什么不能呢?听起来您想使用计时器来更新 UI,那么为什么不直接使用 DispatcherTimer 呢?这几乎就是它的用途!
  • @charles_mager 由于应用程序的设计,我不能使用DispatcherTimer - 这不是我的决定:-(
  • 问题是为什么你不能使用它。您的应用程序的设计如何阻止您使用它?毕竟,它正是您应该使用的工具。
  • 据我了解,当您更新变量 totalRunningTime 时,您希望 Web 控件(标签)不断更新。您每秒触发一个 Timer 并减少变量,然后更新标签。当前代码是否有任何问题,因为我看到您在 CountDownThread 方法中执行所有操作
  • 不会使用像 javascript 这样的客户端脚本来更新 Web 控件上的计时器的更好解决方案。检查以下链接:codeproject.com/Tips/429419/…codeproject.com/Questions/260124/Countdown-timer-in-asp-netforums.asp.net/t/1085601.aspx

标签: c# multithreading timer


【解决方案1】:

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

重新开始:使用 Tasks 不会阻塞 UI 线程;这只是安排在一段时间内完成的工作。在这段时间内,它不会消耗任何线程的时间 - 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();
       }
   }
}

【讨论】:

    【解决方案2】:

    您需要Start() 计时器并在每个滴答声中更新/使 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();
    }   
    

    【讨论】:

    • 倒计时没有开始——标签只显示hh:mm:ss
    • 您的格式已损坏;我使用totalRunningTime.ToString() 在 WinForms 中测试了我的代码,请参阅编辑后的帖子。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-24
    • 1970-01-01
    • 1970-01-01
    • 2013-04-14
    相关资源
    最近更新 更多