尽管.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能不能用。

注意:此博客已停止更新,并迁移至blog.SkyDev.cc,后续都将在新地址更新。



posted on 2009-04-12 21:38  斯克迪亚  阅读(5984)  评论(9编辑  收藏  举报