我有大约20个函数,其中一些应该每秒触发一次,一些,每秒20次,另外一次每分钟两次,我现在有类似的东西:
DateTime nowVar = DateTime.Now;
var lastExecutionFunc1 = nowVar;
var lastExecutionFunc2 = nowVar;
var lastExecutionFunc3 = nowVar;
var lastExecutionFunc4 = nowVar;
DateTime _now = DateTime.Now;
if ((_now - lastExecutionFunc1).TotalSeconds >= 0.1)
{
lastExecutionFunc1 = _now;
//dosomething
}
if ((_now - lastExecutionFunc2).TotalSeconds >= 0.5)
{
lastExecutionFunc2 = _now;
//do something else
}
if ((_now - lastExecutionFunc3).TotalSeconds >= 30)
{
lastExecutionFunc3 = _now;
//do something else
}
.....
虽然这有效,但我不禁认为应该有更优雅的方式来做到这一点。创建一个var来存储每个执行使得核心看起来非常混乱。猜猜我可以使用对,但这也不会太好。
有什么建议吗?
编辑:如果你想看看我想要完成的事情,you can see the whole code here。在第525行。
答案 0 :(得分:3)
你为这个定时活动写了一个无限循环吗?非常糟糕的做法。 如果你们中的任何一个“做某事”持续很长时间,所有其他功能(和主程序)将停止工作。如果你的功能可以独立工作,让他们独立工作,并为每个功能使用不同的计时器。如果某些函数是独占函数,请使用信号量(静态成员)以避免并行工作。
答案 1 :(得分:3)
下面的代码展示了一个带有同步锁的基本调度程序。
using System;
using System.Collections.Generic;
using System.Timers;
namespace TimerUsage
{
class Program
{
static void Main(string[] args)
{
Scheduler scheduler = new Scheduler();
scheduler.ScheduleMethod(100, () => Console.WriteLine("func1"));
scheduler.ScheduleMethod(200, () => Console.WriteLine("func2"));
scheduler.ScheduleMethod(300, () => Console.WriteLine("func3"));
scheduler.ScheduleMethod(1000, () => Console.WriteLine("func4"));
scheduler.Run();
System.Threading.Thread.Sleep(10000);
}
}
public class Scheduler
{
private Dictionary<int, Row> _schedule = new Dictionary<int, Row>();
public void ScheduleMethod(int interval, Action method)
{
Row row;
if (!_schedule.TryGetValue(interval, out row))
{
row = new Row(interval);
_schedule[interval] = row;
}
row.AddMethod(method);
}
public void Run()
{
foreach (var item in _schedule)
{
item.Value.StartTimer();
}
}
}
internal class Row
{
private object _syncLock = new object();
private Timer _timer;
private List<Action> _methods = new List<Action>();
public Row(int interval)
{
_timer = new System.Timers.Timer(interval);
_timer.Elapsed += ExecuteItems;
}
private void ExecuteItems(object sender, ElapsedEventArgs e)
{
lock (_syncLock)
{
foreach (var method in _methods)
{
method();
}
}
}
public void AddMethod(Action method)
{
_methods.Add(method);
}
public void StartTimer()
{
_timer.Start();
}
}
}
答案 2 :(得分:1)
这是一种方法:
我创建了一个使用Action
委托将方法与其间隔绑定的类:
public class ActionInvoker
{
private DateTime _LastRunTime;
private Action _Action;
private double _Interval;
public ActionInvoker(Action action, double interval)
{
_Action = action;
_Interval = interval;
_LastRunTime = DateTime.Now;
}
public void InvokeAction()
{
var now = DateTime.Now;
if ((now - _LastRunTime).TotalMilliseconds >= _Interval)
{
_LastRunTime = now;
_Action.Invoke();
}
}
我添加了一个ActionInvoker
列表作为表单的私有成员:
private List<ActionInvoker> _Actions;
现在,在表单的构造函数中,我已经完成了这个:
_Actions = new List<ActionInvoker>();
_Actions.Add(new ActionInvoker(DoThis, 10000));
_Actions.Add(new ActionInvoker(DoThat, 3000));
现在我在Timer.Tick事件处理程序中的所有内容都是这段代码:
foreach(var ai in _Actions)
{
ai.InvokeAction();
}
当然,这只是一个基本的POC,如果要将参数发送到方法,或者方法返回值,则需要进一步开发它。
另请注意,您最好将这些方法作为async
运行,以防止用户界面冻结,直到完成为止。