其他分享
首页 > 其他分享> > 定时器

定时器

作者:互联网

目录

概念

相关类

namespace System.Threading
{
    public static class Timeout
    {
        public const int Infinite = -1;
        public static readonly TimeSpan InfiniteTimeSpan;
    }
}
namespace System.Threading
{
    public delegate void TimerCallback(object state);
}

Timer

public sealed class Timer : MarshalByRefObject, IDisposable
{
    public Timer(TimerCallback callback);
    public Timer(TimerCallback callback, object state, int dueTime, int period);
    public Timer(TimerCallback callback, object state, TimeSpan dueTime, TimeSpan period);
    public Timer(TimerCallback callback, object state, uint dueTime, uint period);
    public Timer(TimerCallback callback, object state, long dueTime, long period);
    public bool Change(int dueTime, int period);
    public bool Change(TimeSpan dueTime, TimeSpan period);
    public bool Change(uint dueTime, uint period);
    public bool Change(long dueTime, long period);
    public bool Dispose(WaitHandle notifyObject);
    public void Dispose();
}

callback

指定定时器每次触发时,执行的方法。

object state

通过这个参数为回调方法提供实参。定时器每次回调时,都会取最新的object参数的值。

dueTime

定时器第一次触发前等待的时长。如果该值为负值,则此计时器永远不会启动。如果该值为0,则计时器立刻触发第一次回调。如果为正数,则dueTime毫秒后,计时器触发第一次回调。

period

定时器每次触发回调的时间间隔。该值等于0或小于0时,则计时器只触发一次回调(dueTime >= 0)或一次都不触发(dueTime < 0)。该值大于0时,每隔period毫秒,会触发一次回调。

dueTime和period区别

Timer使用方法

先构造后启用

  1. 构造Timer实例

    Timer timer = new Timer(new TimerCallback((state) =>{}));
    timer = new Timer(new TimerCallback((state) => { }), null, Timeout.Infinite, Timeout.Infinite);
    timer = new Timer(new TimerCallback((state) => { }), null, Timeout.InfiniteTimeSpan, Timeout.InfiniteTimeSpan);
    
  2. 使用Change()启动计时器

    timer.Change(100,1000);
    

构造时直接启动

Timer timer = new Timer(new TimerCallback((state) =>{}),null,100,1000);

我们可以利用Change()随时暂停,重启计时器,也可以改变计时器的第一次执行方法之前等待的时间量(截止时间)以及此后的执行期间等待的时间量(时间周期)。

避免多个线程执行回调方法

定时器会在回调方法执行完毕后,再过指定的时间,再进行下一次回调。

static void Main(string[] args)
{
    Timer timer = null;

    timer = new Timer((state) =>
    {
        Thread.Sleep(2000);
        Console.WriteLine("执行定时任务");
        timer.Change(1000, Timeout.Infinite);
    }, null, 1000, Timeout.Infinite);

    Console.ReadLine();
}

这个示例,会每隔3秒打印一次“执行定时任务”。

MSDN示例代码

using System;
using System.Threading;

class TimerExample
{
    static void Main()
    {
        // Create an AutoResetEvent to signal the timeout threshold in the
        // timer callback has been reached.
        var autoEvent = new AutoResetEvent(false);
        
        var statusChecker = new StatusChecker(10);

        // Create a timer that invokes CheckStatus after one second, 
        // and every 1/4 second thereafter.
        Console.WriteLine("{0:h:mm:ss.fff} Creating timer.\n", 
                          DateTime.Now);
        var stateTimer = new Timer(statusChecker.CheckStatus, 
                                   autoEvent, 1000, 250);

        // When autoEvent signals, change the period to every half second.
        autoEvent.WaitOne();
        stateTimer.Change(0, 500);
        Console.WriteLine("\nChanging period to .5 seconds.\n");

        // When autoEvent signals the second time, dispose of the timer.
        autoEvent.WaitOne();
        stateTimer.Dispose();
        Console.WriteLine("\nDestroying timer.");
    }
}

class StatusChecker
{
    private int invokeCount;
    private int  maxCount;

    public StatusChecker(int count)
    {
        invokeCount  = 0;
        maxCount = count;
    }

    // This method is called by the timer delegate.
    public void CheckStatus(Object stateInfo)
    {
        AutoResetEvent autoEvent = (AutoResetEvent)stateInfo;
        Console.WriteLine("{0} Checking status {1,2}.", 
            DateTime.Now.ToString("h:mm:ss.fff"), 
            (++invokeCount).ToString());

        if(invokeCount == maxCount)
        {
            // Reset the counter and signal the waiting thread.
            invokeCount = 0;
            autoEvent.Set();
        }
    }
}
// The example displays output like the following:
//       11:59:54.202 Creating timer.
//       
//       11:59:55.217 Checking status  1.
//       11:59:55.466 Checking status  2.
//       11:59:55.716 Checking status  3.
//       11:59:55.968 Checking status  4.
//       11:59:56.218 Checking status  5.
//       11:59:56.470 Checking status  6.
//       11:59:56.722 Checking status  7.
//       11:59:56.972 Checking status  8.
//       11:59:57.223 Checking status  9.
//       11:59:57.473 Checking status 10.
//       
//       Changing period to .5 seconds.
//       
//       11:59:57.474 Checking status  1.
//       11:59:57.976 Checking status  2.
//       11:59:58.476 Checking status  3.
//       11:59:58.977 Checking status  4.
//       11:59:59.477 Checking status  5.
//       11:59:59.977 Checking status  6.
//       12:00:00.478 Checking status  7.
//       12:00:00.980 Checking status  8.
//       12:00:01.481 Checking status  9.
//       12:00:01.981 Checking status 10.
//       
//       Destroying timer.

避免出现ObjectDisposeException异常

等待线程池所有的回调线程全部结束

当我们不想再执行定时任务时,如果不在意任务执行的次数,可以直接Dispose();如果在意的话,可以先利用Change( )暂停向线程池排队线程,然后利用Dispose(WaitHandle waitHandle)确定线程池里面所有的回调线程都执行完毕,再继续后续流程。

如果回调方法中调用了Timer的成员,可能会出现调用了一个对象的Dispose()后再次调用该对象的其他成员导致抛出异常的情况,对于Timer则是ObjectDisposeException,我们最好处理一下该可能的异常。

When a timer is no longer needed, use the Dispose method to free the resources held by the timer. Note that callbacks can occur after the Dispose() method overload has been called, because the timer queues callbacks for execution by thread pool threads. You can use the Dispose(WaitHandle) method overload to wait until all callbacks have completed.

The callback method executed by the timer should be reentrant, because it is called on ThreadPool threads. The callback can be executed simultaneously on two thread pool threads if the timer interval is less than the time required to execute the callback, or if all thread pool threads are in use and the callback is queued multiple times.

标签:status,定时器,Checking,timer,线程,Timer,回调
来源: https://www.cnblogs.com/LiuwayLi/p/14857358.html