我使用了timer.elapsed但是这个只能调用具有相同时间间隔的方法,例如
timer.interval = 1000;
timer.elapsed += first();
timer.elapsed+= second();
此呼叫每1秒钟第一次和第二次,我需要在3秒钟呼叫一个,另一个在5秒钟呼叫。
答案 0 :(得分:1)
您可以简单地使用多个计时器。
timer1.Inverval = 3000;
timer1.Elapsed += first();
timer2.Interval = 5000;
timer2.Elapsed += second();
答案 1 :(得分:1)
如果你真的不能添加多个计时器,(为什么不呢?)只计算两个区间的最大公约数(GCD)(比如一个函数需要每30秒执行一次,一个需要每45秒执行一次,那么GCD是5秒,所以将定时器设置为每5秒触发一次,但是定时器开始时每6次执行一次FunctionA,而第9次执行功能B.
答案 2 :(得分:1)
如果真的想要只使用一个计时器来执行此操作:
您需要维护一个列表,其中每个条目都包含对要调用的方法的引用,以及应该调用它的时间。 (必须使用绝对时间值,而不是间隔。)
浏览列表,找到时间值最小的条目(最接近现在的时间),并将计时器设置为在该时间点触发。
当计时器触发时,再次遍历列表,并调用任何其调用时间小于或等于的方法。对于调用的每个方法,计算下一次调用该方法的时间。
转到第1步。
这样做,你将基本上重新实现.Net运行时的计时器机制,这是徒劳的练习。所以,用这种方式做 不 会更好,而是使用多个计时器。
答案 3 :(得分:0)
我不确定你为什么要这样做,但你可以做类似以下的事情:
public class MultiIntervalTimer: IDisposable
{
private readonly Timer innerTimer;
private readonly IReadOnlyDictionary<int, MultiIntervalTimerCallbackInfo> callbackInfos;
private long totalElapsedMiliseconds;
private readonly int innerTimerInterval;
private object syncRoot = new object();
private bool disposed;
public MultiIntervalTimer(Dictionary<int, MultiIntervalTimerCallbackInfo> callbacks, int dueTime)
{
if (callbacks == null)
throw new ArgumentNullException(nameof(callbacks));
var innerTimerCallback = new TimerCallback(innerCallback);
callbackInfos = new Dictionary<int, MultiIntervalTimerCallbackInfo>(callbacks);
innerTimerInterval = getGreatestCommonDivisor(callbacks.Keys);
innerTimer = new Timer(innerTimerCallback, null, dueTime, innerTimerInterval);
}
public void Dispose()
{
if (disposed)
return;
innerTimer.Dispose();
disposed = true;
}
private static int getGreatestCommonDivisor(IEnumerable<int> numbers)
{
Debug.Assert(numbers != null);
Debug.Assert(numbers.Any());
var numbersArray = numbers.ToArray();
if (numbersArray.Length == 1)
return numbersArray[0];
if (numbersArray.Length == 2)
return getGreatestCommonDivisor(numbersArray[0], numbersArray[1]);
var trimmedNumbersArray = new int[numbersArray.Length - 1];
Array.Copy(numbersArray, 1, trimmedNumbersArray, 0, trimmedNumbersArray.Length);
return getGreatestCommonDivisor(numbersArray[0], getGreatestCommonDivisor(trimmedNumbersArray));
}
private static int getGreatestCommonDivisor(int left, int right)
{
while (right != 0)
{
var temp = right;
right = left % right;
left = temp;
}
return left;
}
private void innerCallback(object state)
{
Debug.Assert(syncRoot != null);
Debug.Assert(!disposed);
var elapsed = 0L;
lock (syncRoot)
{
totalElapsedMiliseconds += innerTimerInterval;
elapsed = totalElapsedMiliseconds;
}
foreach (var callback in callbackInfos.Where(c => elapsed % c.Key == 0))
{
callback.Value?.Callback(callback.Value.State);
}
}
}
public class MultiIntervalTimerCallbackInfo
{
public MultiIntervalTimerCallbackInfo(TimerCallback callback, object state)
{
if (callback == null)
throw new ArgumentNullException(nameof(callback));
Callback = callback;
State = state;
}
public TimerCallback Callback { get; }
public object State { get; }
}
使用它的方法:
public class State
{
public State()
:this(0)
{ }
private State(int count)
{
Count = count;
}
public int Count { get; private set; }
public void IncrementCount() => Count++;
}
public static void Main(string[] args)
{
var state = new State();
bool stop = false;
var intervalCallback1 = new MultiIntervalTimerCallbackInfo(new System.Threading.TimerCallback(c =>
{
Console.WriteLine($"Interval 1: Call #{state.Count}. Thread Id: {Thread.CurrentThread.ManagedThreadId}");
state.IncrementCount();
}), state);
var intervalCallback2 = new MultiIntervalTimerCallbackInfo(new System.Threading.TimerCallback(c =>
{
Console.WriteLine($"Interval 2: Call #{state.Count}. Thread Id: {Thread.CurrentThread.ManagedThreadId}");
state.IncrementCount();
}), state);
var intervalCallback3 = new MultiIntervalTimerCallbackInfo(new System.Threading.TimerCallback(c =>
{
Console.WriteLine($"Interval 3: Call #{state.Count}. Thread Id: {Thread.CurrentThread.ManagedThreadId}");
state.IncrementCount();
}), state);
var intervalCallback4 = new MultiIntervalTimerCallbackInfo(new System.Threading.TimerCallback(c =>
{
Console.WriteLine($"Interval 4: Call #{state.Count}. Thread Id: {Thread.CurrentThread.ManagedThreadId}.\r\n Exiting loop", state);
stop = true;
}), state);
var callbacks = new Dictionary<int, MultiIntervalTimerCallbackInfo>() { { 50, intervalCallback1 },
{ 100, intervalCallback2 },
{ 200, intervalCallback3 },
{ 2000, intervalCallback4 } };
using (var timer = new MultiIntervalTimer(callbacks, 1000))
{
while (!stop)
{
}
}
Console.WriteLine($"Total calls: {state.Count}.");
Console.ReadLine();
}
我几乎没有对此进行测试,并且我没有花太多时间考虑多线程的所有影响以及所需的锁定/同步,因此请将此代码作为一种非常初步的方法。 / p>