一種延遲方法調用的實現


需求場景

最近遇到一種場景,需要延遲某個步驟的實現,以便在延遲的過程中能夠及早處理,從而取消任務。 比如,現在的服務器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     }

  運行結果如下:

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM