当前位置:网站首页>Timing manager based on C #
Timing manager based on C #
2022-07-05 03:39:00 【Dotnet cross platform】
problem
We will encounter the following problems when using various systems :
12306 Buy train tickets on if 15 If the payment is not completed within minutes, the order will be automatically cancelled .
Reserved seats in the conference venue , If 10 If the payment is not completed within minutes, the reservation will be automatically cancelled .
After the specified time , I need to perform a task .
I have done many systems before , It is often a specific task that is performed on a regular basis . And the appeal problem involves the timing task of sliding window time .
such as : I am in the morning 10 spot 20 I booked a train ticket separately , I need to 15 Pay in minutes , Otherwise, the order will be canceled . Hundreds of people may book other train tickets at the same time , I need to be in everyone's 15 Check when the minute deadline expires , If it has not been paid, the order will be cancelled automatically .
programme
After we figure out the problem to be solved , Let's think about the plan . Experienced programmers will immediately think of the following solutions :
Use the delayed delivery function of message queue , Send a delay after each order is successfully added 15 Minute delay message . Order status processor 15 Message received in minutes , Check payment status , If not, cancel the order .
Redis There are similar functions , The principle is roughly the same .
But I don't want to use the function of message queue , Because delayed message delivery is a technical implementation , I hope to use code to reflect this business implementation , So use pure code to deal with him .( I'm not trying to reinvent the wheel , Because this is a business requirement , There will be a need for change and expansion , So I decided to try to increase my experience )
Algorithm ideas :
Our demand timing is 15 Within minutes, , Assume no more than 1 Hours or days .( If exceeded 1 Hour , This design can be extended , This article will not be discussed for the time being )
We can consider dividing an hour into 3600 second , Every second represents a location to store all expired orders , When placing an order, according to the current time add 15 Minute intervals , We can get it 15 Minutes later , Add this order to the corresponding location .
Data structure selection :
We choose C# The latest concurrent dictionary provided in is used as the basic data structure ,Key The value is 3600 The value of each second in seconds , The content is a queue used to store all orders at that point in time .

public ConcurrentDictionary<int, ConcurrentQueue<IJob>> jobs = new ConcurrentDictionary<int, ConcurrentQueue<IJob>>();We have thought about the data structure , In fact, most of the functions are completed , The design of the code is basically settled .
Code implementation ( I like experimenting with console applications )
Set up a timing manager
public class TimerManager { // The concurrent dictionary stores the tasks that need to be checked ( Here can be the order check task , Each task can contain an order Id) public ConcurrentDictionary<int, ConcurrentQueue<IJob>> jobs = new ConcurrentDictionary<int, ConcurrentQueue<IJob>>(); private Timer timer; public TimerManager() { // Every interval 1 Once per second . Synchronize with the current time . timer = new Timer(ProcessJobs, null, 0, 1000); } }Add a task to the dictionary
/// <summary> /// Add a task to the time dictionary /// </summary> /// <param name="timeKey"> Calculated according to the delay time key value </param> /// <param name="duetime"> Millisecond unit </param> /// <exception cref="NotImplementedException"></exception> public void AddJob(IJob job, TimeSpan duetime) { var key = GetKey(duetime); ConcurrentQueue<IJob> queue = new ConcurrentQueue<IJob>(); queue.Enqueue(job); jobs.AddOrUpdate(key, queue, (key, jobs) => { jobs.Enqueue(job); return jobs; }); }Calculate according to time Key Methods
/// <summary> /// Generate the current key value according to the delay time /// </summary> /// <param name="duetime"></param> /// <returns></returns> private int GetKey(TimeSpan duetime) { var currentDateTime = DateTime.Now; // Due time var targetDateTime = currentDateTime.Add(duetime); // Don't forget to convert minutes into seconds , Then add it to the delay time to get Key var key = targetDateTime.Minute * 60 + targetDateTime.Second; return key; }Add tasks to the dictionary
/// <summary> /// Add a task to the time dictionary /// </summary> /// <param name="job"> Tasks to be performed </param> /// <param name="duetime"> How many intervals do you check </param> public void AddJob(IJob job, TimeSpan duetime) { var key = GetKey(duetime); ConcurrentQueue<IJob> queue = new ConcurrentQueue<IJob>(); queue.Enqueue(job); // This is the method of concurrent dictionary , This is when Key If it doesn't exist, add a new value , When Key Existence exists in Key Add a new task to the queue of jobs.AddOrUpdate(key, queue, (key, jobs) => { jobs.Enqueue(job); return jobs; }); }The method of processing tasks when the timer executes every second , Cycle to get tasks from the queue until all tasks are processed .
private async void ProcessJobs(object state) { // Calculate according to the current time Key value var key = DateTime.Now.Minute * 60 + DateTime.Now.Second; Console.WriteLine(key); // lookup Key Value the corresponding task queue and process . bool keyExists = jobs.TryGetValue(key, out var jobQueue); if (keyExists) { IJob job; while(jobQueue.TryDequeue(out job)) { await job.Run(); } } }Design in code IJob and Job An implementation of , For ease of understanding , This job Not doing much . If you need to expand to check the order , You can record the order here Id, When creating a task, place an order ID Associated with the task , In this way, the timer can find the corresponding order when processing this task .
public interface IJob { Task Run(); } /// <summary> /// Represents a job /// </summary> public class Job : IJob { public Guid JobId { get; set; } public Job() { JobId = Guid.NewGuid(); } public async Task Run() { Console.WriteLine(" Job Id: " + JobId.ToString() + " is running."); await Task.Delay(2000); Console.WriteLine(" Job Id:" + JobId.ToString() + " have completed."); } }The main program Programe Call the timing manager
using TimerTest; Console.WriteLine("Hello, World!"); TimerManager timerManager = new TimerManager(); Job job1 = new Job(); // Add a task 1 Execute in minutes timerManager.AddJob( job1, TimeSpan.FromMinutes(1)); // Adding another task in 2 Execute in minutes Job job2 = new Job(); timerManager.AddJob(job2, TimeSpan.FromMinutes(2)); Console.ReadLine();
Execution results
You can see in the results that , Mission 1 stay 1014 Is processed on the key value of ,1014 The time corresponding to the key value of is 16:54 second , That is, when I run this program 1 Minutes later .

| Mission | Add the time | execution time |
|---|---|---|
| First mission ( timing 1 minute ) | 15:54 | 16:54 |
| Second task ( timing 2 minute ) | 15:54 | 17:54 |
Mission 2 stay 1074 Is processed on the key value of ,1074 The corresponding time is 17:54 second perform . It can be seen from the above table that the program runs normally and the result is .

summary
This is a simple console program that verifies the implementation of the timing manager , We will 1 Hours are divided into 3600 second , Every second corresponds to one Key value , On this value, we store the tasks that need to be processed . When adding tasks , We also use the same algorithm to determine this Key value . When processing, divide by... According to the current time Key Value to process .
In this case , In the real world , We have 3600 individual Key Value can store all orders submitted by users every second , Time has not passed 1 I will deal with the corresponding task in seconds .
What can be improved later
We can add this class to ASP.NET MVC in , Use dependency injection for single instance lifecycle , Concurrent dictionaries and queues are thread safe , So you can use it safely .
We can expand Job Method , Add more information according to the business logic to facilitate processing . For example, processing orders ID, Or any other business ID.
The method of processing tasks can adopt multiple consumers to execute concurrently , Increase processing speed .
You can store task entities in the database , In order to deal with sudden downtime accidents, tasks can be rebuilt quickly .
Of course we can use Hangfire To easily realize this business .
var jobId = BackgroundJob.Schedule( () => Console.WriteLine("Delayed!"), TimeSpan.FromDays(7)); // Just change this to minutes
Finally, I wish .NET 20 Happy anniversary .
边栏推荐
- In MySQL Association query, the foreign key is null. What if the data cannot be found?
- The perfect car for successful people: BMW X7! Superior performance, excellent comfort and safety
- Is there any way to change the height of the uinavigationbar in the storyboard without using the UINavigationController?
- Devtools的簡單使用
- 有個疑問 flink sql cdc 的話可以設置並行度麼, 並行度大於1會有順序問題吧?
- [Chongqing Guangdong education] 2777t green space planning reference questions of National Open University in autumn 2018
- 【web审计-源码泄露】获取源码方法,利用工具
- Anchor free series network yolox source code line by line explanation Part 2 (a total of 10, ensure to explain line by line, after reading, you can change the network at will, not just as a participan
- How can we truncate the float64 type to a specific precision- How can we truncate float64 type to a particular precision?
- SQL performance optimization skills
猜你喜欢

Azkaban installation and deployment

New interesting test applet source code_ Test available

Azkaban overview

Machine learning experiment report 1 - linear model, decision tree, neural network part

The perfect car for successful people: BMW X7! Superior performance, excellent comfort and safety

Pdf things

Qrcode: generate QR code from text

Sqoop command

Redis6-01nosql database

How about programmers' eyesight| Daily anecdotes
随机推荐
【PHP特性-变量覆盖】函数的使用不当、配置不当、代码逻辑漏洞
英语必备词汇3400
[learning notes] month end operation -gr/ir reorganization
[wp][入门]刷弱类型题目
Mongodb common commands
Learning notes of raspberry pie 4B - IO communication (I2C)
[vérification sur le Web - divulgation du code source] obtenir la méthode du code source et utiliser des outils
Port, domain name, protocol.
FBO and RBO disappeared in webgpu
程序员的视力怎么样? | 每日趣闻
About authentication services (front and back, login, registration and exit, permission management)
The latest blind box mall, which has been repaired very popular these days, has complete open source operation source code
UE4 DMX和grandMA2 onPC 3.1.2.5的操作流程
Kubernetes - identity and authority authentication
LeetCode 234. Palindrome linked list
【软件逆向-基础知识】分析方法、汇编指令体系结构
Talk about the SQL server version of DTM sub transaction barrier function
Performance of calling delegates vs methods
Class inheritance in C #
LeetCode 237. Delete nodes in the linked list