簡體   English   中英

system.timers.timer 的生命周期以及如何調用方法每 x 次注入數據? c#

[英]Cycle of life of a system.timers.timer and how to call a method to inject data every x time? c#

我是新來的,也是這個世界上的新人。 我 2 個月前開始學習 c# 所以請耐心等待。

為了練習目的,我正在做某種模擬服務,我在其中注入一批數據,我的代碼用它來做一些事情,但我想這樣做,我的數據只在每 x 段時間驗證一次,這就是我迷路的地方。 也許這比我假設的更簡單,但我去了文檔: https://learn.microsoft.com/en-us/do.net/api/system.timers.timer?view.net-6.0但它沒有幫我。 我知道這是我需要的,因為我需要像文檔中所說的那樣的東西:

例如,假設您有一個連續將銷售訂單發布到數據庫的在線銷售應用程序。 編譯運輸說明的服務對一批訂單進行操作,而不是單獨處理每個訂單。 您可以使用計時器每 30 分鍾開始一次批處理。

但我找不到任何地方可以看到它的實施位置或它的生命周期應該如何。 也許是我在以一種比實際情況更困難的方式思考這個問題?

對於這段代碼,我有一個控制台應用程序,我在其中“模擬”了我的服務調用三次來處理 de databatch:

    public class Program
    {
       static void Main(string[] args)
       {
         BatchWithTimerTest test = new();
         Inventory inventory = new()
         {
           //data to compare with my inData
         }
         DataBatch inData = new()
         {
            //input data
         }
         test.setup(inventory);
         test.init();
         test.ProcessData(inData);
    
         test.ProcessData(inData);
    
         test.ProcessData(inData);
       }

    }

和我的 BatchWithTimerTest class:

public class BatchWithTimerTest
{
   private Inventory _inventory;
   private System.Timers.Timer timer;
   ReaderWriterLockSlim innerLock = new ReaderWriterLockSlim();

   public void setup(Inventory inventory)
   {
      _inventory = inventory;
   }

   public void init()
   {
      timer =new(30000);
      timer.Start();
      timer.Elapsed += (sender, e) => TimerElapsed(sender, e);
   }

   public void ProcessData(DataBatch inData)
   {
      //process my input data
   }

   private void TimerElapsed(object? sender, ElapsedEventArgs e)
   {
      innerLock.EnterWriteLock();
      try
      {
          // should process my input data every 30 secs but how?
      }
      finally
      {
         innerLock.ExitWriteLock();
      }
   }
}

我確信我的問題出在關於它如何工作的概念上,但我整天都在尋找信息,但我看不到任何有用的信息(或者也許我只是不知道去哪里找)。 在我看來,這應該做的是在初始化我的計時器時配置,每 30 秒運行一個 processData 方法來接收新的輸入數據,但這可能是錯誤的。

我不知道這樣的問題是否被允許,但任何幫助將不勝感激

我正在展示我在此類問題中建議的代碼方式,以及我的解決方案。

首先,定義數據源,它返回一個數據序列並打印每個數據的生成時間。 這里需要回調(在實際項目中可能是一些等效事件),因為您不希望自旋循環快速檢查全局值。

        static Random rand = new Random();
        static void DataSource(object o)
        {
            Action<int> callBack = (Action<int>)o;
            int data = 0;
            while (data++ < 10)
            {
                Console.WriteLine($"produced data {data} at {DateTime.Now:mm:ss:ff}");
                callBack(data);
                //random can be removed, to be more minimal,
                //but keeping random looks like more interesting
                Thread.Sleep(TimeSpan.FromMilliseconds(rand.Next(100, 1000)));
            }
            Console.WriteLine("DataSource stopped");
        }

然后定義real time handler ,目的是測試數據源,並與其他解決方案進行比較。
您需要在另一個線程中運行數據源,因為我們通常希望我們的計時器在主 (UI) 線程上。

        static void RealTimeHandle(int n)
        {
            Console.WriteLine($"Consumed {n} at {DateTime.Now:mm:ss:ff}");
        }

        static void Main(string[] args)
        {
            new Thread(DataSource).Start((Action<int>)RealTimeHandle);
            Console.WriteLine("End of Main");
            Console.ReadKey();
        }

output

End of Main
produced data 1 at 50:09:50
Consumed 1 at 50:09:51
produced data 2 at 50:10:25
Consumed 2 at 50:10:26
produced data 3 at 50:10:39
Consumed 3 at 50:10:39
produced data 4 at 50:11:02
Consumed 4 at 50:11:03
produced data 5 at 50:11:60
Consumed 5 at 50:11:60
produced data 6 at 50:12:33
Consumed 6 at 50:12:33
produced data 7 at 50:12:98
Consumed 7 at 50:12:99
produced data 8 at 50:13:39
Consumed 8 at 50:13:39
produced data 9 at 50:14:20
Consumed 9 at 50:14:20
produced data 10 at 50:14:97
Consumed 10 at 50:14:97
DataSource stopped

最后,緩沖處理程序

        static Queue<int> buffer = new Queue<int>();
        static System.Timers.Timer timer;
        static void BufferHandle(int n)
        {
            buffer.Enqueue(n);
        }

        static void Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            int cnt = buffer.Count;
            for (int i = 0; i < cnt; i++)
            {
                Console.WriteLine($"Consumed {buffer.Dequeue()} at {DateTime.Now:mm:ss:ff}");
            }
        }
        static void Main(string[] args)
        {
            new Thread(DataSource).Start((Action<int>)BufferHandle);
            timer = new System.Timers.Timer(3000);//consume data every 3 seconds
            timer.Elapsed += Timer_Elapsed;
            timer.Start();
            //need consider stop timer somewhere
            Console.WriteLine("End of Main");
            Console.ReadKey();
        }

output

End of Main
produced data 1 at 51:10:00
produced data 2 at 51:10:67
produced data 3 at 51:11:63
produced data 4 at 51:11:75
produced data 5 at 51:12:23
produced data 6 at 51:12:87
Consumed 1 at 51:13:01
Consumed 2 at 51:13:01
Consumed 3 at 51:13:01
Consumed 4 at 51:13:02
Consumed 5 at 51:13:02
Consumed 6 at 51:13:02
produced data 7 at 51:13:44
produced data 8 at 51:14:15
produced data 9 at 51:14:47
produced data 10 at 51:14:98
DataSource stopped
Consumed 7 at 51:16:01
Consumed 8 at 51:16:01
Consumed 9 at 51:16:01
Consumed 10 at 51:16:01

筆記:

  1. 這段代碼只是展示了最小的、可重現的概念,並不意味着好的設計模式。
  2. 我不考慮線程之間的競爭條件,因為時間跨度足夠長。 我沒有看到你的相關要求。
  3. 如果您仍然不了解計時器的生命周期,或者有更好的緩沖區處理方法,請發表評論,我會嘗試更新。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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