zoukankan      html  css  js  c++  java
  • 一种延迟方法调用的实现

    需求场景

    最近遇到一种场景,需要延迟某个步骤的实现,以便在延迟的过程中能够及早处理,从而取消任务。 比如,现在的服务器CPU过高了,则系统记录下来,然后开始发送邮件通知用户,但是如果在10秒之内CPU恢复了;或者我不希望用户得知这个CPU的信息,因为我就在现场,我可以及时知道怎么处理这种情况,这个时候准备拨打电话的这个方法的调用就不能被执行,需要延迟一段时间,以便能够被取消——以上场景仅供参考。

    代码实现

      以下是我的一个实现方式,供大家讨论,或者有更好的方式可以改进。

    这种方法旨在能够方便的延迟任意方法的执行:

    定义任务接口 

      这是一个基本的线程任务的接口,包括任务名称、线程的运行状态、启停线程。

    1     interface ITask
    2     {
    3         string Name { get; }
    4         bool IsRunning { get; }
    5         void Start();
    6         void Stop();
    7         void Run();

    8     } 

      定义延迟的信息类

      保存当前需要延迟的方法,以及需要延迟的时间等

      1         class LazyItem

     2         {
     3             private readonly int _timeout;
     4             private readonly DateTime _enqueueTime;
     5 
     6             public bool IsTimeout
     7             {
     8                 get { return (DateTime.Now - _enqueueTime).TotalSeconds > _timeout; }
     9             }
    10             public string Key { getprivate set; }
    11             public Action Continue { getprivate set; }
    12 
    13             public LazyItem(string key, int timeout, Action continueAction)
    14             {
    15                 _enqueueTime = DateTime.Now;
    16                 _timeout = timeout;
    17                 Key = key;
    18                 Continue = continueAction;
    19             }
    20         }

      延迟的实现

      主要是执行一个定时的任务,去检测被延迟的方法是否达到了超时的时间,如果达到,则执行该方法。另外,提供一个可供取消方法的函数。

      1     class LazyInvoker : ITask

     2     {
     3         public string Name
     4         {
     5             get { return "Lazy Invoke Task"; }
     6         }
     7 
     8         public bool IsRunning { getprivate set; }
     9 
    10         private readonly ConcurrentDictionary<string, LazyItem> _lazyActions = new ConcurrentDictionary<string, LazyItem>();
    11 
    12         public void Start()
    13         {
    14             Task.Factory.StartNew(Run);
    15             IsRunning = true;
    16         }
    17 
    18         public void Stop()
    19         {
    20             IsRunning = false;
    21         }
    22 
    23         /// <summary>
    24         /// 检测被延迟的任务,达到超时时间则触发
    25         /// </summary>
    26         /// Created by:marvin(2014/10/11 12:14)
    27         public void Run()
    28         {
    29             while (IsRunning)
    30             {
    31                 CheckContinue();
    32                 Thread.Sleep(1 * 1000);
    33             }
    34         }
    35 
    36         private void CheckContinue()
    37         {
    38             if (_lazyActions.Count <= 0return;
    39 
    40             var removeKeys = (from lazyItem in _lazyActions where lazyItem.Value.IsTimeout select lazyItem.Key).ToList();
    41             if (removeKeys.Count <= 0return;
    42 
    43             foreach (var key in removeKeys)
    44             {
    45                 LazyItem tmp;
    46                 if (_lazyActions.TryRemove(key, out tmp))
    47                 {
    48                     tmp.Continue();
    49                 }
    50             }
    51         }
    52 
    53         /// <summary>
    54         /// 延迟工作
    55         /// </summary>
    56         /// <param name="id">The identifier.</param>
    57         /// <param name="lazyTimeout">The lazy timeout.</param>
    58         /// <param name="continueAction">The continue action.</param>
    59         /// Created by:marvin(2014/10/11 11:48)
    60         public void LazyDo(string id, int lazyTimeout, Action continueAction)
    61         {
    62             if (!_lazyActions.ContainsKey(id))
    63             {
    64                 if (_lazyActions.TryAdd(id, new LazyItem(id, lazyTimeout, continueAction)))
    65                 {
    66                     //Console.WriteLine("lazy action : {0} , timeout : {1}", id, lazyTimeout);
    67                 }
    68             }
    69         }
    70 
    71         /// <summary>
    72         /// 取消任务
    73         /// </summary>
    74         /// <param name="actionKey">The action key.</param>
    75         /// Created by:marvin(2014/10/11 12:02)
    76         public void Cancel(string actionKey)
    77         {
    78             if (_lazyActions.ContainsKey(actionKey))
    79             {
    80                 LazyItem tmp;
    81                 if (_lazyActions.TryRemove(actionKey, out tmp))
    82                 {
    83                     Console.WriteLine("lazy action “{0}” had removed", tmp.Key);
    84                 }
    85             }
    86         }
    87     }

     测试

      1     class Program

     2     {
     3         static void Main(string[] args)
     4         {
     5             var lazyInvoker = new LazyInvoker();
     6             lazyInvoker.Start();
     7 
     8             //延迟7秒运行
     9             lazyInvoker.LazyDo(Guid.NewGuid().ToString(), 7, DoSomething);
    10             Thread.Sleep(5 * 1000);
    11 
    12             //延迟3秒运行,但是3秒的时候被取消
    13             var id = Guid.NewGuid().ToString();
    14             lazyInvoker.LazyDo(id, 5, DoSomething);
    15             Thread.Sleep(3 * 1000);
    16             lazyInvoker.Cancel(id);
    17 
    18             Console.ReadKey();
    19         }
    20 
    21         private static void DoSomething()
    22         {
    23             Console.WriteLine("Now time is :" + DateTime.Now.ToString("HH:mm:ss"));
    24         }
    25     }

      运行结果如下:

     

  • 相关阅读:
    vim初试(Hello World)
    CSP201809-2 买菜(超简单的方法!!)
    CSP202006-2 稀疏向量
    CSP202012-2 期末预测之最佳阈值
    浮点数表示
    结构体
    全排列-康托展开及逆展开
    CA-031 上手Games101环境 Games101环境怎么配置
    计算机图形学 实验四 AET算法
    计算机图形学 实验三 梁氏裁剪算法
  • 原文地址:https://www.cnblogs.com/marvin/p/lazyInvokeMethod.html
Copyright © 2011-2022 走看看