[英]How to invoke multiple instances using timer events in C#
問題陳述
我有一個用 C# 編寫的模塊代碼,它等待一個名為“開始”的主題,一旦收到,我需要根據 om 時間間隔定期發送某些數據。 我需要以這樣一種方式來適應我的邏輯,即可以使用不同的元數據值多次調用“開始”主題,並且所有這些都必須使用相同的邏輯運行它自己的實例。
我面臨的問題
現在代碼總是只運行一個“SendPeriodicTelemetry”實例,即使“start”主題被多次調用。
代碼片段示例
以下三個類是按照調用順序給出的
public static async void MessageReceiveAsync(object sender, MqttApplicationMessageReceivedEventArgs e)
{
Console.WriteLine($"Message received on topic: '{e.ApplicationMessage.Topic}'. Payload: {msg}");
try
{
if (e.ApplicationMessage.Topic.Contains("methods"))
{
await PublisherClass.PublishToMethod(topicElement, msg);
}
}
}
public static class PublisherClass
{
public static bool StartInvoked { get; set; }
public static int StartCmdCount { get; set; } = 0;
public static async Task PublishToMethod(string methodName, string message)
{
try
{
string topic;
var sendPeriodicTelemetries = new SendPeriodicTelemetry[10];
switch (methodName)
{
case "stop":
for (int i = 0; i < StartCmdCount; i++)
{
Console.WriteLine($"start command index to stop: {i}");
sendPeriodicTelemetries[StartCmdCount].aTimer.Stop();
sendPeriodicTelemetries[StartCmdCount].aTimer.Dispose();
}
StartInvoked = false;
StartCmdCount = 0;
await CommonMethods.AckMethod(CommonMethods.listMessage, CommonMethods.requestId, MethodNames.sendTimeSeries);
break;
case "start":
sendPeriodicTelemetries[StartCmdCount] = new SendPeriodicTelemetry();
sendPeriodicTelemetries[StartCmdCount].TsAlarmAndEventTopicAndPayload(rawPayload, objId);
sendPeriodicTelemetries[StartCmdCount].aTimer = new System.Timers.Timer(timeIntervel);
sendPeriodicTelemetries[StartCmdCount].SetTimer(timeIntervel, sendPeriodicTelemetries[StartCmdCount].aTimer);
StartCmdCount++;
break;
}
}
catch(Exception exception)
{
Console.WriteLine($"Exception occurred: {exception.ToString()}");
}
}
}
public class SendPeriodicTelemetry
{
public void TsAlarmAndEventTopicAndPayload(JObject rawPayload, string objId)
{
}
public void SetTimer(int timeInterval, Timer timer)
{
if (!PublisherClass.StartInvoked)
{
PublisherClass.StartInvoked = true;
timer.Elapsed += SendPeriodic;
timer.AutoReset = true;
timer.Enabled = true;
}
}
public async void SendPeriodic(Object source, ElapsedEventArgs e)
{
Console.WriteLine("Starting to send periodic Telemetry at {0:HH:mm:ss.fff}", e.SignalTime);
await SendPeriodicTimeSeries(PublisherClass.TimeSeriesTopic, PublisherClass.TelemetrySingle, PublisherClass.Configuration);
await SendPeriodicAlarm(PublisherClass.AlarmTopic, PublisherClass.AlarmSingle);
await SendPeriodicEvent(PublisherClass.EventTopic, PublisherClass.EventSingle);
}
public async Task SendPeriodicTimeSeries(string topic, TelemetrySingle payload, JObject configuration)
{
}
public async Task SendPeriodicAlarm(string topic, AlarmSingle payload)
{
}
public async Task SendPeriodicEvent(string topic, EventSingle payload)
{
}
}
場景流程
考慮從“MessageReceiveAsync”我收到一個主題,該主題包含一個名為“start”的方法(不是 C# 方法),第一次使用一些元數據,然后使用該方法名稱(“start”)調用“PublishToMethod”
然后根據在“開始”情況下收到的元數據,我根據收到的元數據以及“開始”命令將計時器啟動到特定間隔。
然后將在設定的時間間隔發送以下所有三個數據
await SendPeriodicTimeSeries(PublisherClass.TimeSeriesTopic, PublisherClass.TelemetrySingle, PublisherClass.Configuration); await SendPeriodicAlarm(PublisherClass.AlarmTopic, PublisherClass.AlarmSingle); await SendPeriodicEvent(PublisherClass.EventTopic, PublisherClass.EventSingle);
考慮從“MessageReceiveAsync”我收到另一個主題,該主題包含一個方法(不是 C# 方法),第二次使用不同的元數據再次調用“start”。 它可以擊中任意次數。
然后再次為定時器設置特定的時間間隔,定時器事件必須定期為 go 用於不同類型的元數據
前面的周期數據也應該像往常一樣提前go
此外,每當調用“停止”方法時,所有實例的定期計時器事件都應該停止。
實際結果
一旦我第二次收到“開始”,第一次調用的元數據值全部切換到第二次調用的值,並且總是周期性數據用於最新調用的值。 只有一個實例始終在運行。 我想發送與調用“開始”的次數一樣多的實例的定期數據。
預期結果
應調用計時器事件的多個實例,並且以下方法應根據收到的元數據繼續發送數據
await SendPeriodicTimeSeries(PublisherClass.TimeSeriesTopic,
PublisherClass.TelemetrySingle, PublisherClass.Configuration);
await SendPeriodicAlarm(PublisherClass.AlarmTopic, PublisherClass.AlarmSingle);
await SendPeriodicEvent(PublisherClass.EventTopic, PublisherClass.EventSingle);
Timer object 初始化出現問題。 它仍然來自 static class,因此使用“SendPeriodicTelemetry”實例級別屬性對其進行了更改。 然后現在我可以以指定的時間間隔調用多個實例。 為了停止那些基於時間的事件,我需要處理 Timer。 而已。 達到了我的目的。 並且不需要將“SendPeriodicTelemetry”object 初始化為數組來實現這一點。
public static async void MessageReceiveAsync(object sender, MqttApplicationMessageReceivedEventArgs e)
{
Console.WriteLine($"Message received on topic: '{e.ApplicationMessage.Topic}'. Payload: {msg}");
try
{
if (e.ApplicationMessage.Topic.Contains("methods"))
{
await PublisherClass.PublishToMethod(topicElement, msg);
}
}
}
public static class PublisherClass
{
public static List<System.Timers.Timer> SendPeriodicTimerObjs { get; set; } = new List<System.Timers.Timer>();
public static async Task PublishToMethod(string methodName, string message)
{
try
{
switch (methodName)
{
case "start":
case "stop":
var sendPeriodicObj = new SendPeriodicTelemetry();
sendPeriodicObj.periodicTimer = new System.Timers.Timer();
SendPeriodicTimerObjs.Add(sendPeriodicObj.periodicTimer);
if (methodName == "start")
{
sendPeriodicObj.TsAlarmAndEventTopicAndPayload(rawPayload, objId);
sendPeriodicObj.periodicTimer.Interval = timeIntervel;
sendPeriodicObj.SetTimer(timeIntervel, sendPeriodicObj.periodicTimer);
}
else
{
sendPeriodicObj.periodicTimer.Stop();
foreach(var timer in SendPeriodicTimerObjs)
{
timer.Dispose();
}
SendPeriodicTimerObjs.Clear();
}
break;
}
}
catch(Exception exception)
{
Console.WriteLine($"Exception occurred: {exception.ToString()}");
}
}
}
public class SendPeriodicTelemetry
{
public System.Timers.Timer periodicTimer;
public void TsAlarmAndEventTopicAndPayload(JObject rawPayload, string objId)
{
}
public void SetTimer(int timeInterval, Timer timer)
{
Console.WriteLine($"Inside SetTimer method");
StartInvoked = true;
timer.Elapsed += SendPeriodic;
timer.AutoReset = true;
timer.Enabled = true;
}
public async void SendPeriodic(Object source, ElapsedEventArgs e)
{
Console.WriteLine("Starting to send periodic Telemetry at {0:HH:mm:ss.fff}", e.SignalTime);
await SendPeriodicTimeSeries(PublisherClass.TimeSeriesTopic, PublisherClass.TelemetrySingle, PublisherClass.Configuration);
await SendPeriodicAlarm(PublisherClass.AlarmTopic, PublisherClass.AlarmSingle);
await SendPeriodicEvent(PublisherClass.EventTopic, PublisherClass.EventSingle);
}
public async Task SendPeriodicTimeSeries(string topic, TelemetrySingle payload, JObject configuration)
{
}
public async Task SendPeriodicAlarm(string topic, AlarmSingle payload)
{
}
public async Task SendPeriodicEvent(string topic, EventSingle payload)
{
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.