适用于WinForm的一个定时器类

鉴于.NET提供的Timer组件在多实例运行时可能出现混乱问题,本文介绍了一种利用BackgroundWorker组件封装的自定义定时器实现方法,该定时器能有效避免事件错乱,并提供简单易用的API。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

尽管.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  定时器
ExpandedBlockStart.gifContractedBlock.gif    
{
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
        
/// 创建一个定时器对象。
        
/// </summary>
        
/// <param name="定时">指示定时时间,以毫秒为单位。</param>
        
/// <param name="间歇时间">指示定时之中的间歇时间,用于检查是否取消执行。</param>

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

ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
        
/// 指示定时时间,以毫秒为单位。
        
/// </summary>

        public int 定时
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{
            
get
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                
return _定时;
            }

            
set
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                _定时 
= value;
            }

        }

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

        public int 间歇时间
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{
            
get
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                
return _间歇时间;
            }

            
set
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                _间歇时间 
= value;
            }

        }

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

            
set
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                _后台处理进程 
= value;
            }

        }

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

            
set
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                _附件 
= value;
            }

        }

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

        public bool 执行中
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{
            
get
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                
return _执行中;
            }

        }

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

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

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

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

ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
        
/// 达到定时事件代理
        
/// </summary>

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

            
set
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                _取消触发完毕事件 
= value;
            }

        }

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

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

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

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


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

        }

    }

 

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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值