首页 > 编程语言 >C#定时任务

C#定时任务

时间:2022-12-12 11:36:04浏览次数:34  
标签:task C# private 任务 new 定时 超时 public

 

 1     /// <summary>
 2     /// 耗时计数器
 3     /// </summary>
 4     public class ElapsedTimer
 5     {
 6         // 创建时默认为创建时间,这样不调用 Start 也可以
 7         private DateTime _StartTime = DateTime.Now;
 8 
 9         // 计时开始
10         public void Start()
11         {
12             _StartTime = DateTime.Now;
13         }
14 
15         // 计时结束(输出毫秒)
16         public long Over()
17         {
18             var timespan = DateTime.Now - _StartTime;
19             return Convert.ToInt32(timespan.TotalMilliseconds);
20         }
21 
22         // 取得间隔
23         public TimeSpan Span()
24         {
25             return DateTime.Now - _StartTime;
26         }
27 
28         /// <summary>
29         /// 静态方法,运行指定函数,返回耗时结果
30         /// </summary>
31         /// <param name="action"></param>
32         /// <returns></returns>
33         public static TimeSpan Elapsed(Action action)
34         {
35             ElapsedTimer tcc = new ElapsedTimer();
36             action();
37             return tcc.Span();
38         }
39     }

 

 1     public class QueueTask<T>
 2     {     
 3         // 对象标识
 4         public T ObjectKey { get; set; }
 5         
 6         // 回调方法
 7         public Action<T, String> Callback { get; set; }
 8 
 9         /// <summary>
10         /// 用于保存一些回调时使用的上下文信息
11         /// </summary>
12         public string Context { get; set; }
13     }

 

 1     public class QueueTaskRunner<T>
 2     {  
 3         // 任务队列,由任务运行线程逐个执行
 4         private Queue<QueueTask<T>> _TaskRunQueue = new Queue<QueueTask<T>>();
 5         // 用来同步操作任务队列,使得线程安全(生产者,消费者模式)
 6         private object _RunLocker = new object();
 7        
 8         // 超时任务执行线程
 9         private Thread _TaskRunThread;
10         // 用于同步操作任务队列的线程信号(生产者,消费者通知作用)
11         private EventWaitHandle _WaitHandle = new AutoResetEvent(false);
12         // 用于退出执行线程的一个标识
13         private bool _Working = true;
14         
15         /// <summary>
16         /// 创建实例时,开启:任务执行线程
17         /// </summary>
18         public QueueTaskRunner()
19         { 
20             _TaskRunThread = new Thread(new ThreadStart(TaskRunning));
21             _TaskRunThread.Start();            
22         }
23 
24         /// <summary>
25         /// 任务执行线程主体
26         /// </summary>
27         private void TaskRunning()
28         {
29             while (_Working)
30             {
31                 QueueTask<T> task = null;
32                 lock (_RunLocker)   
33                 {
34                     if (_TaskRunQueue.Count > 0)
35                     {
36                         task = _TaskRunQueue.Dequeue();  
37                     }
38                 }
39                 // 存在超时任务执行其回调
40                 if (task != null)
41                 {
42                     task.Callback(task.ObjectKey, task.Context);
43                 }
44                 else
45                 {
46                     // 等待生产者通知
47                     _WaitHandle.WaitOne();
48                 }
49             }
50         } 
51 
52         #region 以下为向外开放的功能
53 
54         /// <summary>
55         /// 添加任务
56         /// </summary>
57         /// <param name="objectKey"></param>
58         /// <param name="callback"></param>
59         public void AddTask(T objectKey, Action<T, String> callback)
60         {
61             AddTask(objectKey, callback, null);
62         }
63 
64         /// <summary>
65         /// 添加任务
66         /// </summary>
67         /// <param name="objectKey"></param>
68         /// <param name="callback"></param>
69         /// <param name="context"></param>
70         public void AddTask(T objectKey, Action<T, String> callback, String context)
71         {
72             QueueTask<T> task = new QueueTask<T>();
73             task.ObjectKey = objectKey; 
74             task.Callback = callback; 
75             task.Context = context;
76 
77             // 加入任务执行队列
78             lock (_RunLocker)
79             {
80                 _TaskRunQueue.Enqueue(task); 
81             }
82             // 有生产,则通知执行线程(消费者)
83             _WaitHandle.Set();
84         } 
85 
86         /// <summary>
87         /// 销毁时,退出线程执行体,释放内存
88         /// </summary>
89         public void Dispose()
90         { 
91             _Working = false;
92             _WaitHandle.Set();
93             _TaskRunThread.Join();
94             _WaitHandle.Close();
95         }
96 
97         #endregion
98 
99     }

 

 1     /// <summary>
 2     /// 超时回调的委托
 3     /// </summary>
 4     /// <typeparam name="T"></typeparam>
 5     /// <param name="objectKey"></param>
 6     /// <param name="context"></param>
 7     public delegate void TimeoutCallback<T>(T objectKey, String context);
 8 
 9     /// <summary>
10     /// 超时任务信息
11     /// </summary>
12     /// <typeparam name="T"></typeparam>
13     public class TimeoutTask<T>
14     {
15         // 任务标识(由超时任务运行器自动分配)
16         public long TaskId { get; set; }
17         // 对象标识
18         public T ObjectKey { get; set; }
19         // 超时秒数
20         public int TimeoutSeconds { get; set; }
21         /// <summary>
22         /// 以秒为单位的 Tick 值,由超时任务运行器根据当前时间加上超时秒数计算设置
23         /// DateTime.Ticks 是以 10ns(10纳秒) 为单位
24         /// 将其除以 10 单位为 ws(微秒),再除以 1000 为 ms(毫秒),再除以 1000 为 s(秒)
25         /// 累计为 DateTime.Ticks / 10000000
26         /// </summary>
27         public long ExecuteSecondTicks { get; set; }
28         // 超时回调方法
29         public TimeoutCallback<T> Callback { get; set; }
30         /// <summary>
31         /// 用于保存一些回调时使用的上下文信息
32         /// </summary>
33         public String Context { get; set; }
34     }

 

  1     /// <summary>
  2     /// 超时任务运行器
  3     /// 专为超时时间到达后执行的任务,在超时时间到达之间,可以随时移除
  4     /// </summary>
  5     /// <typeparam name="T"></typeparam>
  6     public class TimeoutTaskRunner<T>
  7     {        
  8         // 为添加的超时任务分配的 TaskId 任务标识序列
  9         private long _TaskIdSequence = 0;
 10 
 11         // 超时检测者,每秒扫描是否达到超时,超时则加入超时任务队列
 12         private System.Timers.Timer _TimeoutChecker = new System.Timers.Timer();
 13 
 14         // 以 TaskId(任务标识) 为 KEY 的任务清单字典
 15         private Dictionary<long, TimeoutTask<T>> _TaskIdDictionary = new Dictionary<long, TimeoutTask<T>>();
 16         // 以 ObjectId(任务相关对象标识) 为 KEY 的任务字典,因每个对象可以有多个超时任务,所以为列表
 17         private Dictionary<T, List<TimeoutTask<T>>> _TaskObjectKeyDictionary = new Dictionary<T, List<TimeoutTask<T>>>();
 18         // 用于同步操作上述两个清单字典,使得线程安全
 19         private object _DictionaryLocker = new object(); 
 20 
 21         // 已超时任务队列,由任务运行线程逐个执行
 22         private Queue<TimeoutTask<T>> _TaskRunQueue = new Queue<TimeoutTask<T>>();
 23         // 用来同步操作任务队列,使得线程安全(生产者,消费者模式)
 24         private object _RunLocker = new object();
 25        
 26         // 超时任务执行线程
 27         private Thread _TaskRunThread;
 28         // 用于同步操作任务队列的线程信号(生产者,消费者通知作用)
 29         private EventWaitHandle _WaitHandle = new AutoResetEvent(false);
 30         // 用于退出执行线程的一个标识
 31         private bool _Working = true;
 32 
 33         
 34         /// <summary>
 35         /// 创建实例时,开启:(1)超时检测者 (2)超时任务执行线程
 36         /// </summary>
 37         public TimeoutTaskRunner()
 38         {
 39             // (1)超时检测者
 40             _TimeoutChecker.Interval = 1000;
 41             _TimeoutChecker.Elapsed += new System.Timers.ElapsedEventHandler(CheckTimerTick);
 42             _TimeoutChecker.Start();
 43 
 44             // (2)超时任务执行线程
 45             _TaskRunThread = new Thread(new ThreadStart(TaskRunning));
 46             _TaskRunThread.Start();            
 47         } 
 48 
 49         /// <summary>
 50         /// 超时任务检测者
 51         /// 对于,时间已经超过了设定的超时时间的,加入超时任务执行队列
 52         /// </summary>
 53         /// <param name="sender"></param>
 54         /// <param name="e"></param>
 55         private void CheckTimerTick(object sender, System.Timers.ElapsedEventArgs e)
 56         {
 57             long secondTicks = DateTime.Now.Ticks / 10000000;
 58             // 遍历,把时间已到达超过超时时间的找出来
 59             lock (_DictionaryLocker)
 60             {
 61                 foreach (var key in _TaskIdDictionary.Keys.ToList())
 62                 {
 63                     var task = _TaskIdDictionary[key];
 64                     if (_TaskIdDictionary[key].ExecuteSecondTicks <= secondTicks)
 65                     {
 66                         // 加入超时任务执行队列,并移除清单
 67                         lock (_RunLocker)
 68                         {
 69                             _TaskRunQueue.Enqueue(task);
 70                             RemoveTimeoutTask(task.TaskId);
 71                         }
 72                         // 有生产,则通知执行线程(消费者)
 73                         _WaitHandle.Set();
 74                     }
 75                 }
 76             }
 77         }
 78 
 79         /// <summary>
 80         /// 超时任务执行线程主体
 81         /// </summary>
 82         private void TaskRunning()
 83         {
 84             while (_Working)
 85             {
 86                 TimeoutTask<T> task = null;
 87                 lock (_RunLocker)   
 88                 {
 89                     if (_TaskRunQueue.Count > 0)
 90                     {
 91                         task = _TaskRunQueue.Dequeue();  
 92                     }
 93                 }
 94                 // 存在超时任务执行其回调
 95                 if (task != null)
 96                 {
 97                     task.Callback(task.ObjectKey, task.Context);
 98                 }
 99                 else
100                 {
101                     // 等待生产者通知
102                     _WaitHandle.WaitOne();
103                 }
104             }
105         }
106 
107         /// <summary>
108         /// 获取下一个任务标识
109         /// </summary>
110         /// <returns></returns>
111         [MethodImplAttribute(MethodImplOptions.Synchronized)]
112         private long GetNextTaskId()
113         {
114             _TaskIdSequence = (_TaskIdSequence + 1) % long.MaxValue;
115             return _TaskIdSequence;
116         } 
117 
118         #region 以下为向外开放的功能
119 
120         public long AddTimeoutTask(T objectKey, int timeoutSeconds, TimeoutCallback<T> callback)
121         {
122             return AddTimeoutTask(objectKey, timeoutSeconds, callback, null);
123         }
124 
125         /// <summary>
126         /// 指定对象标识,超时时长(秒为单位),超时执行回调,加入到超时检测字典中
127         /// </summary>
128         /// <param name="objectKey"></param>
129         /// <param name="timeoutSeconds"></param>
130         /// <param name="callback"></param>
131         /// <param name="context"></param>
132         /// <returns></returns>
133         public long AddTimeoutTask(T objectKey, int timeoutSeconds, TimeoutCallback<T> callback, String context)
134         {
135             TimeoutTask<T> task = new TimeoutTask<T>();
136             task.ObjectKey = objectKey;
137             task.TimeoutSeconds = timeoutSeconds;
138             task.Callback = callback;
139             long taskId = GetNextTaskId();
140             task.TaskId = taskId;
141             task.ExecuteSecondTicks = DateTime.Now.Ticks / 10000000 + timeoutSeconds;
142             task.Context = context;
143 
144             lock (_DictionaryLocker)
145             {
146                 // 以任务标识为主键的任务清单
147                 _TaskIdDictionary[taskId] = task;
148                 // 以对象标识为主键的任务清单
149                 if (_TaskObjectKeyDictionary.ContainsKey(objectKey))
150                 {
151                     _TaskObjectKeyDictionary[objectKey].Add(task);
152                 }
153                 else
154                 {
155                     List<TimeoutTask<T>> list = new List<TimeoutTask<T>>();
156                     list.Add(task);
157                     _TaskObjectKeyDictionary[objectKey] = list;
158                 }
159             }
160             return taskId;
161         }
162 
163         /// <summary>
164         /// 根据对象标识移除超时任务设置
165         /// </summary>
166         /// <param name="objectKey"></param>
167         public void RemoveTimeoutTask(T objectKey)
168         {
169             lock (_DictionaryLocker)
170             {
171                 if (_TaskObjectKeyDictionary.ContainsKey(objectKey))
172                 {
173                     // 在任务标识为主键的清单中移除相应的该对象的多个超时任务
174                     foreach (var task in _TaskObjectKeyDictionary[objectKey])
175                     {
176                         _TaskIdDictionary.Remove(task.TaskId);
177                     }
178                     _TaskObjectKeyDictionary[objectKey].Clear();
179                 }
180             }
181         }
182 
183         /// <summary>
184         /// 根据任务标识移除超时任务设置
185         /// </summary>
186         /// <param name="taskId"></param>
187         public void RemoveTimeoutTask(long taskId)
188         {
189             lock (_DictionaryLocker)
190             {
191                 if (_TaskIdDictionary.ContainsKey(taskId))
192                 {
193                     var task = _TaskIdDictionary[taskId];
194                     _TaskIdDictionary.Remove(taskId);
195                     // 在对象标识为主键的清单移除相应的超时任务
196                     _TaskObjectKeyDictionary[task.ObjectKey].Remove(task);
197                 }
198             }
199         }
200 
201         /// <summary>
202         /// 销毁时,退出线程执行体,释放内存
203         /// </summary>
204         public void Dispose()
205         {
206             _Working = false;
207             _WaitHandle.Set();
208             _TaskRunThread.Join(100);
209             _WaitHandle.Close();
210         }
211 
212         #endregion
213 
214     }

 

标签:task,C#,private,任务,new,定时,超时,public
From: https://www.cnblogs.com/kingkie/p/16975576.html

相关文章