简体   繁体   English

在C#中使用计时器线程

[英]Using a timer thread in C#

I am doing an application that needs a some kind of a system clock, a clock that counts ticks. 我正在做一个需要某种系统时钟的应用程序,它需要计算滴答声。 I should be able to get the count value and set it. 我应该能够获得计数值并进行设置。

I have done it using Thread library in the Python language, yet I could not do the same thing with the Timer class in C#. 我已经使用Python语言中的Thread库完成了此操作,但对于C#中的Timer类却无法做同样的事情。 As someone new to .NET, I am not sure how this timer class works. 作为.NET的新手,我不确定此计时器类如何工作。 I would love to to be able to implement the same clock using .NET. 我希望能够使用.NET来实现相同的时钟。

Here is my Python code, so you can get an idea of what I'm talking about. 这是我的Python代码,因此您可以了解我在说什么。

class SystemClock(threading.Thread):

  def __init__(self , timeUnit , sched):
      self.val = 0

      self.unit = timeUnit
      self.stp= False
      self.sched = sched
      threading.Thread.__init__(self)

  def run(self):
      while not self.stp:
          self.val +=1
          time.sleep(self.unit)

  def getSystemTime(self):
      return self.val

  def stop(self):
      self.stp = True

I appreciate your help; 我感谢您的帮助;

Why not just use System.Diagnostics.Stopwatch , as that's exactly what it's for. 为什么不只使用System.Diagnostics.Stopwatch ,因为这正是它的用途。

// at the start of your program
Stopwatch SystemClock = Stopwatch.StartNew();

// any time you want to see how much time has elapsed
long ticks = SystemClock.ElapsedTicks;

If you really need to be able to set the value, then wrap this in a class that has a base_time value (in ticks), and then add the elapsed ticks to your base time to get the time you want. 如果确实需要设置该值,则将其包装在具有base_time值(以滴答为单位)的类中,然后将经过的滴答添加到基准时间中以获得所需的时间。

Is there any reason why you don't just retrieve a DateTime at the start and, as necessary to have the value, use an DateTime.Now.Subtract(origDateTime) and use the TimeSpan result for what you need? 是否有任何原因为什么您不只是在开始时检索DateTime,并根据需要使用DateTime.Now.Subtract(origDateTime)来获取值,并根据需要使用TimeSpan结果? Or is this updating something with every tick? 还是每次更新都会更新某些内容?

EDIT Also, as with Timers, you set a "Tick" interval, so you don't need to sleep them. 编辑此外,与计时器一样,您可以设置“滴答”间隔,因此您无需休眠它们。 Every tick will execute the callback saving you the trouble of using a while...sleep. 每次滴答都会执行回调,从而省去了使用...睡眠的麻烦。 But bare in bind, while in threading territory, and I can't verify as it's been a while since I've used timers, you may need to lock() the variable you're modifying as it's in a separate thread as nothing is securing that another method isn't altering the same value. 但是在绑定领域时,它几乎没有绑定,而且由于使用定时器,我已经无法验证了,您可能需要锁定要修改的变量,因为它在单独的线程中,所以什么也没有确保另一种方法不会改变相同的值。

EDITv3 EDITv3

Here's version 3 of the edit. 这是编辑的版本3。 You have two classes, both avoiding the use of a timer (which your CPU will thank me later ;-p) SystemClock is a typical one-per-second interval rate. 您有两个类,都避免使用计时器(您的CPU稍后会感谢我;-p) SystemClock是典型的每秒间隔时间。 VariableSystemClock allows you to specify the rate of the increases. VariableSystemClock允许您指定增加的速率。 I also changed the way you get the value from a property to a method, and even used inheritance. 我还更改了从属性到方法获取值的方法,甚至使用了继承。 ;-) ;-)

SystemClock.cs SystemClock.cs

public class SystemClock
{
    protected DateTime _start;

    public SystemClock()
    {
        this._start = DateTime.UtcNow;
    }

    public virtual Int32 getSystemTime()
    {
        return Convert.ToInt32(Math.Floor(DateTime.UtcNow.Subtract(this._start).TotalSeconds));
    }
}

VariableSystemClock.cs VariableSystemClock.cs

public class VariableSystemClock : SystemClock
{
    private TimeSpan _interval;

    public VariableSystemClock(TimeSpan interval)
        : base()
    {
        this._interval = interval;
    }

    public override Int32 getSystemTime()
    {
        Double ellapsed = DateTime.UtcNow.Subtract(this._start).Ticks / this._interval.Ticks;
        return Convert.ToInt32(Math.Floor(ellapsed));
    }
}

program.cs (so you can test it in a console application (project->new->console application) program.cs(因此您可以在控制台应用程序中进行测试(project-> new-> console应用程序)

class Program
{
    static void Main(string[] args)
    {
        SystemClock oncePerSecond = new SystemClock();
        VariableSystemClock oncePerInterval = new VariableSystemClock(TimeSpan.FromSeconds(2));

        Console.WriteLine("Start:");
        Console.WriteLine("  oncePerSecond:   {0}", oncePerSecond.getSystemTime());
        Console.WriteLine("  oncePerInterval: {0}", oncePerInterval.getSystemTime());
        Console.WriteLine();

        for (Int32 i = 0; i < 10; i++)
        {
            // sleep three seconds
            System.Threading.Thread.Sleep(TimeSpan.FromSeconds(2));

            // display output
            Console.WriteLine("Interval {0}:", i);
            Console.WriteLine("  oncePerSecond:   {0}", oncePerSecond.getSystemTime());
            Console.WriteLine("  oncePerInterval: {0}", oncePerInterval.getSystemTime());
            Console.WriteLine();
        }

        Console.WriteLine("End:");
        Console.WriteLine("  oncePerSecond:   {0}", oncePerSecond.getSystemTime());
        Console.WriteLine("  oncePerInterval: {0}", oncePerInterval.getSystemTime());
        Console.WriteLine();
    }
}

Feel free to play with both the oncePerInterval construct and the Sleep within the for loop. 随时可以使用一次afterPerInterval构造和for循环中的Sleep。

线程计时器可能更多。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM