c# - 使用 System.Threading 在 C# 中同时运行多个计时器
问题描述
我有用于从网络位置提取报告的服务。要求是每 5 分钟我需要调出报告 1,每 10 分钟报告 2 和每 3 小时报告 3、4、5。因此,我在一个单独的工作类的方法中创建了一个计时器,我在其中使用了 System.Threading.Timer 的 5 个实例。报告正在被删除,但顺序不正确。如何运行计时器以使报告可以按特定顺序提取或使用 1 个计时器来安排以特定方式提取报告?
这是我到目前为止所做的:
private async void pullReports()
{
try
{
await _logger.Info($"Start Report Monitoring");
Timer timer = new Timer
(
async e => await Service.ReportMonitoring(reportNum: 1),
null,
TimeSpan.Zero,
TimeSpan.FromMinutes(5)
);
Timer timer2 = new Timer
(
async e => await Service.ReportMonitoring(reportNum: 2),
null,
TimeSpan.Zero,
TimeSpan.FromMinutes(10)
);
Timer timer3 = new Timer
(
async e => await Service.ReportMonitoring(reportNum: 3),
null,
TimeSpan.Zero,
TimeSpan.FromHours(3)
);
Timer timer4 = new Timer
(
async e => await Service.ReportMonitoring(reportNum: 4),
null,
TimeSpan.Zero,
TimeSpan.FromHours(3)
);
Timer timer5 = new Timer
(
async e => await Service.ReportMonitoring(reportNum: 5),
null,
TimeSpan.Zero,
TimeSpan.FromHours(3)
);
}
catch (Exception ex)
{
await _logger.Error($"Start Report Monitoring exception: {ex}");
}
}
任何类型的代码改进都值得赞赏。我认为因为我的方法 Service.ReportMonitoring() 是异步的,这就是扰乱收集顺序的原因。但我不确定。
ReportNum 的代码如下:
private static Task<Stream> ReportMonitoring(int repnum)
{
string _urlDataFormat = "https://{0}/cgi-bin/CGILink?cmd=vtranssetz&period=2&reptnum={1}";
string dataUrl = string.Format(_urlDataFormat, <serverIP>, repnum);
return HttpService.ExecuteGetStreamAsync(dataUrl);
}
解决方案
如果报告的顺序很重要(因此数字较大的应该始终排在数字较小的之后),您应该执行以下操作:
var counter = 0L;
Timer timer = new Timer
(
async _ =>
{
var local = Interlocked.Read(ref counter);
Interlocked.Increment(ref counter);
await ReportMonitoring(1);
if (local % 2 == 0)
{
await ReportMonitoring(2);
}
if (counter % (3 * 12) == 0)
{
await ReportMonitoring(3);
await ReportMonitoring(4);
await ReportMonitoring(5);
}
},
null,
TimeSpan.Zero,
TimeSpan.FromMinutes(5)
);
另请注意:
只要您使用 Timer,就必须保留对它的引用。与任何托管对象一样,当没有对 Timer 的引用时,它会受到垃圾回收的影响。Timer 仍然处于活动状态的事实并不能阻止它被收集。
推荐阅读
- html - 如何修复标题和滚动内容
- java - java 10中的Lazy flatMap实现算法
- mysql - 在 SELECT [MYSQL] 中加入或选择
- android - 访问多个 firebase 项目
- php - 如何使用换行符显示从 oracle 数据库中获取的 JSON 输出
- php - 在 Woocommerce 管理员电子邮件通知中显示购买说明
- c# - 在处理当前消息之前不要阅读下一条 Kafka 消息?
- database - 恢复 TFS 数据库的问题
- cloudera - 使用CDH6 common-hadoop依赖的权限问题
- mysql - sql 同一列中的两个日期格式,不能将其更改为标准日期格式(yy-mm-dd)