首页 > 代码库 > 一种延迟方法调用的实现
一种延迟方法调用的实现
需求场景
最近遇到一种场景,需要延迟某个步骤的实现,以便在延迟的过程中能够及早处理,从而取消任务。 比如,现在的服务器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();
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 { get; private set; }
11 public Action Continue { get; private 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 }
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 { get; private set; }
11 public Action Continue { get; private 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 }
延迟的实现
主要是执行一个定时的任务,去检测被延迟的方法是否达到了超时的时间,如果达到,则执行该方法。另外,提供一个可供取消方法的函数。
class LazyInvoker : ITask
{
public string Name
{
get { return "Lazy Invoke Task"; }
}
public bool IsRunning { get; private set; }
private readonly ConcurrentDictionary<string, LazyItem> _lazyActions = new ConcurrentDictionary<string, LazyItem>();
public void Start()
{
Task.Factory.StartNew(Run);
IsRunning = true;
}
public void Stop()
{
IsRunning = false;
}
/// <summary>
/// 检测被延迟的任务,达到超时时间则触发
/// </summary>
/// Created by:marvin(2014/10/11 12:14)
public void Run()
{
while (IsRunning)
{
if (_lazyActions.Count > 0)
{
var removeKeys = (from lazyItem in _lazyActions where lazyItem.Value.IsTimeout select lazyItem.Key).ToList();
if (removeKeys.Count > 0)
{
foreach (var key in removeKeys)
{
LazyItem tmp;
if (_lazyActions.TryRemove(key, out tmp))
{
tmp.Continue();
}
}
}
}
Thread.Sleep(1 * 1000);
}
}
/// <summary>
/// 延迟工作
/// </summary>
/// <param name="id">The identifier.</param>
/// <param name="lazyTimeout">The lazy timeout.</param>
/// <param name="continueAction">The continue action.</param>
/// Created by:marvin(2014/10/11 11:48)
public void LazyDo(string id, int lazyTimeout, Action continueAction)
{
if (!_lazyActions.ContainsKey(id))
{
if (_lazyActions.TryAdd(id, new LazyItem(id, lazyTimeout, continueAction)))
{
Console.WriteLine("lazy action : {0} , timeout : {1}", id, lazyTimeout);
}
}
}
/// <summary>
/// 取消任务
/// </summary>
/// <param name="actionKey">The action key.</param>
/// Created by:marvin(2014/10/11 12:02)
public void Cancel(string actionKey)
{
if (_lazyActions.ContainsKey(actionKey))
{
LazyItem tmp;
if (_lazyActions.TryRemove(actionKey, out tmp))
{
Console.WriteLine("lazy action “{0}” had removed", tmp.Key);
}
}
}
}
public string Name
{
get { return "Lazy Invoke Task"; }
}
public bool IsRunning { get; private set; }
private readonly ConcurrentDictionary<string, LazyItem> _lazyActions = new ConcurrentDictionary<string, LazyItem>();
public void Start()
{
Task.Factory.StartNew(Run);
IsRunning = true;
}
public void Stop()
{
IsRunning = false;
}
/// <summary>
/// 检测被延迟的任务,达到超时时间则触发
/// </summary>
/// Created by:marvin(2014/10/11 12:14)
public void Run()
{
while (IsRunning)
{
if (_lazyActions.Count > 0)
{
var removeKeys = (from lazyItem in _lazyActions where lazyItem.Value.IsTimeout select lazyItem.Key).ToList();
if (removeKeys.Count > 0)
{
foreach (var key in removeKeys)
{
LazyItem tmp;
if (_lazyActions.TryRemove(key, out tmp))
{
tmp.Continue();
}
}
}
}
Thread.Sleep(1 * 1000);
}
}
/// <summary>
/// 延迟工作
/// </summary>
/// <param name="id">The identifier.</param>
/// <param name="lazyTimeout">The lazy timeout.</param>
/// <param name="continueAction">The continue action.</param>
/// Created by:marvin(2014/10/11 11:48)
public void LazyDo(string id, int lazyTimeout, Action continueAction)
{
if (!_lazyActions.ContainsKey(id))
{
if (_lazyActions.TryAdd(id, new LazyItem(id, lazyTimeout, continueAction)))
{
Console.WriteLine("lazy action : {0} , timeout : {1}", id, lazyTimeout);
}
}
}
/// <summary>
/// 取消任务
/// </summary>
/// <param name="actionKey">The action key.</param>
/// Created by:marvin(2014/10/11 12:02)
public void Cancel(string actionKey)
{
if (_lazyActions.ContainsKey(actionKey))
{
LazyItem tmp;
if (_lazyActions.TryRemove(actionKey, out tmp))
{
Console.WriteLine("lazy action “{0}” had removed", tmp.Key);
}
}
}
}
测试
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 }
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 }
运行结果如下:
一种延迟方法调用的实现
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。