簡體   English   中英

如何使用 C# 中的計時器事件調用多個實例

[英]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)
        {
           
        }
    }

場景流程

  1. 考慮從“MessageReceiveAsync”我收到一個主題,該主題包含一個名為“start”的方法(不是 C# 方法),第一次使用一些元數據,然后使用該方法名稱(“start”)調用“PublishToMethod”

  2. 然后根據在“開始”情況下收到的元數據,我根據收到的元數據以及“開始”命令將計時器啟動到特定間隔。

  3. 然后將在設定的時間間隔發送以下所有三個數據

     await SendPeriodicTimeSeries(PublisherClass.TimeSeriesTopic, PublisherClass.TelemetrySingle, PublisherClass.Configuration); await SendPeriodicAlarm(PublisherClass.AlarmTopic, PublisherClass.AlarmSingle); await SendPeriodicEvent(PublisherClass.EventTopic, PublisherClass.EventSingle);
  4. 考慮從“MessageReceiveAsync”我收到另一個主題,該主題包含一個方法(不是 C# 方法),第二次使用不同的元數據再次調用“start”。 它可以擊中任意次數。

  5. 然后再次為定時器設置特定的時間間隔,定時器事件必須定期為 go 用於不同類型的元數據

  6. 前面的周期數據也應該像往常一樣提前go

  7. 此外,每當調用“停止”方法時,所有實例的定期計時器事件都應該停止。

實際結果

一旦我第二次收到“開始”,第一次調用的元數據值全部切換到第二次調用的值,並且總是周期性數據用於最新調用的值。 只有一個實例始終在運行。 我想發送與調用“開始”的次數一樣多的實例的定期數據。

預期結果

應調用計時器事件的多個實例,並且以下方法應根據收到的元數據繼續發送數據

        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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM