【发布时间】:2017-10-16 05:58:15
【问题描述】:
我正在实施一项计划的工作,例如方法,并已缩小到方法。一个实现定时器间隔,另一个基于任务延迟。
我也考虑过使用 Azure 计时器触发的网络作业,但它们不能在多实例模式下工作。实际上,在多实例应用程序中,只有一个触发器在其中一个实例中触发,而其他触发器被锁定,因此增加我的应用程序的实例计数不会增加触发的事件数量。
方法 A(定时器间隔)
using System;
using System.Threading.Tasks;
using System.Timers;
public class Example
{
public static void Main()
{
var aTimer = new Timer();
aTimer.Interval = 5000;
aTimer.Elapsed += OnTimedEventA;
aTimer.AutoReset = true;
aTimer.Enabled = true;
var bTimer = new System.Timers.Timer();
bTimer.Interval = 2000;
bTimer.Elapsed += OnTimedEventB;
bTimer.AutoReset = true;
bTimer.Enabled = true;
Console.WriteLine("Press the Enter key to exit the program at any time... ");
Console.ReadLine();
}
private static void OnTimedEventA(Object source, System.Timers.ElapsedEventArgs e)
{
Task.Run(() =>
{
Console.WriteLine("The Elapsed event A was raised at {0}", DateTime.Now);
});
}
private static void OnTimedEventB(Object source, System.Timers.ElapsedEventArgs e)
{
Task.Run(() =>
{
Console.WriteLine("The Elapsed event B was raised at {0}", DateTime.Now);
});
}
}
方法 B(任务延迟)
using System;
using System.Threading.Tasks;
public class Example
{
public static void Main()
{
EventAAsync();
EventBAsync();
Console.WriteLine("Press the Enter key to exit the program at any time... ");
Console.ReadLine();
}
private static async Task EventAAsync()
{
while (true)
{
Task.Run(() =>
{
Console.WriteLine("The Elapsed event A was raised at {0}", DateTime.Now);
});
await Task.Delay(TimeSpan.FromSeconds(5));
}
}
private static async Task EventBAsync()
{
while (true)
{
Task.Run(() =>
{
Console.WriteLine("The Elapsed event B was raised at {0}", DateTime.Now);
});
await Task.Delay(TimeSpan.FromSeconds(2));
}
}
}
方法 A 和方法 B 在功能上都是一样的。 他们都以 5s 和 2s 的固定间隔调用火灾事件 A 和 B,然后忘记了。现在我试图了解这两种方法的优缺点。最后,事件本身在不同的线程上运行。在理论上和实践中,应该采用这两者中的哪一个来处理许多这样的事件触发器,以便在多个实例中进行缩放。
也欢迎任何其他方法。
【问题讨论】:
-
Task.Delay在内部使用相同的Timer,所以选择你更喜欢的。 -
@Evk 除了使用延迟之外,它就像一次性计时器,而不是定期运行的计时器。一击计时器有问题并导致时钟随时间漂移。因此,长时间运行后,2 秒和 5 秒的间隔将不同步。
-
对于方法 B,一般来说,我建议您:(1)
await Task.WhenAll(workTask, delayTask)而不是等待 just 延迟,以避免重入,以及 (2)添加取消令牌并使用while (!cancellationToken.IsCancellationRequested)。
标签: c#