• 适用于WinForm的一个定时器类


    尽管.Net已经提供了3个Timer,我仍然要自己利用BackgroundWorker组件封装这么一个定时器来使用。

    主要原因是System.Windows.Forms以及System.Threading.Timer的Timer同时运行多个的时候会产生令人发狂的错乱,停止其中一个Timer的时候,可能会引发其他Timer注册的事件,对此类灵异事件,查遍互联网后只在MSDN发现了这么一段说明:

    由于所有 Timer 组件都在主应用程序线程上操作,所以在 Windows 窗体应用程序中的任意 Timer 上调用 Stop 都可以导致来自应用程序中其他 Timer 组件的消息被立即处理。如果有两个 Timer 组件,分别设置为 700 毫秒和 500 毫秒,并且从第一个 Timer 调用 Stop,则应用程序可能首先接收第二个组件的事件回调。如果这证明有问题,请考虑转为使用 System.Threading 命名空间中的 Timer 类。

    而System.Threading.Timer的Timer又让我感到非常晦涩难用,所以就造了一个山寨版的定时器:

        public class 定时器
        
    {
            
    /// <summary>
            
    /// 创建一个定时器对象。
            
    /// </summary>
            
    /// <param name="定时">指示定时时间,以毫秒为单位。</param>
            
    /// <param name="间歇时间">指示定时之中的间歇时间,用于检查是否取消执行。</param>

            public 定时器(int 定时, int 间歇时间)
            
    {
                
    this.定时 = 定时;
                
    if (间歇时间 < 10throw new Exception("间歇时间不得小于10毫秒!");
                
    this.间歇时间 = 间歇时间;
            }

            
    /// <summary>
            
    /// 指示定时时间,以毫秒为单位。
            
    /// </summary>

            public int 定时
            
    {
                
    get
                
    {
                    
    return _定时;
                }

                
    set
                
    {
                    _定时 
    = value;
                }

            }

            
    private int _定时;
            
    /// <summary>
            
    /// 指示定时之中的间歇时间,用于检查是否取消执行。
            
    /// </summary>

            public int 间歇时间
            
    {
                
    get
                
    {
                    
    return _间歇时间;
                }

                
    set
                
    {
                    _间歇时间 
    = value;
                }

            }

            
    private int _间歇时间;
            
    private BackgroundWorker 后台处理进程
            
    {
                
    get
                
    {
                    
    return _后台处理进程;
                }

                
    set
                
    {
                    _后台处理进程 
    = value;
                }

            }

            
    private BackgroundWorker _后台处理进程;
            
    private object 附件
            
    {
                
    get
                
    {
                    
    return _附件;
                }

                
    set
                
    {
                    _附件 
    = value;
                }

            }

            
    private object _附件;
            
    /// <summary>
            
    /// 指示定时器是否处于运行状态
            
    /// </summary>

            public bool 执行中
            
    {
                
    get
                
    {
                    
    return _执行中;
                }

            }

            
    private bool _执行中;
            
    /// <summary>
            
    /// 启动定时器,如果定时器已经启动,则引发异常。
            
    /// </summary>
            
    /// <param name="附件">在定时完成时可能被使用到的传递对象。</param>

            public void 执行(object 附件)
            
    {
                
    if (执行中) throw new Exception("定时器已启动!");
                _执行中 
    = true;
                
    this.附件 = 附件;
                后台处理进程 
    = new BackgroundWorker();
                后台处理进程.WorkerSupportsCancellation 
    = true;
                后台处理进程.DoWork 
    += new DoWorkEventHandler(b_DoWork);
                后台处理进程.RunWorkerCompleted 
    += new RunWorkerCompletedEventHandler(b_RunWorkerCompleted);
                后台处理进程.RunWorkerAsync(
    this);
            }

            
    /// <summary>
            
    /// 请求中止执行,如果定时器尚未启动,则引发异常。
            
    /// </summary>

            public void 中止(bool 取消触发完毕事件)
            
    {
                
    if (!执行中) throw new Exception("定时器尚未启动!");
                
    this.取消触发完毕事件 = 取消触发完毕事件;
                后台处理进程.CancelAsync();
            }

            
    /// <summary>
            
    /// 达到定时事件代理
            
    /// </summary>

            public delegate void 执行完毕代理(定时器 sender, object 附件, bool 是否为用户取消);
            
    private bool 取消触发完毕事件
            
    {
                
    get
                
    {
                    
    return _取消触发完毕事件;
                }

                
    set
                
    {
                    _取消触发完毕事件 
    = value;
                }

            }

            
    private bool _取消触发完毕事件;
            
    /// <summary>
            
    /// 达到定时事件
            
    /// </summary>

            public event 执行完毕代理 执行完毕事件;

            
    void b_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
            
    {
                
    if (e.Error != nullthrow e.Error;
                
    if (!取消触发完毕事件&&执行完毕事件 != null)
                
    {
                    var o 
    = e.Result as 定时器;
                    执行完毕事件(o, o.附件, e.Cancelled);
                }

                _执行中 
    = false;
                后台处理进程.Dispose();
            }


            
    void b_DoWork(object sender, DoWorkEventArgs e)
            
    {
                var o 
    = e.Argument as 定时器;
                e.Result 
    = o;
                
    int x = 0;
                
    while (true)
                
    {
                    
    if (x >= o.定时 || (sender as BackgroundWorker).CancellationPending) break;
                    Thread.Sleep(o.间歇时间);
                    x 
    += o.间歇时间;
                }

            }

        }

    使用起来很简单,“new”了之后“执行()”就可以了。

    使用了WinForm的BackgroundWorker组件,所以不晓得ASP.Net能不能用。

  • 相关阅读:
    VS2015复制VS2013的项目,编译报错
    Asp.Net MVC的几个文件上传方式
    一个基于Jquery的涂鸦插件
    Js 自定义日期格式的正则表达式验证
    无聊做的小游戏,斗牛.html
    MSSql Server 自定义导出
    Asp.Net Ambiguous match found 错误另一种解决方法
    韩天峰(Rango)推荐书目
    微信创建菜单报 must use utf-8 charset hint 错误
    InstallShield 2015 LimitedEdition VS2012 覆盖安装
  • 原文地址:https://www.cnblogs.com/SkyD/p/timer.html
Copyright © 2020-2023  润新知