当前位置:网站首页>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 .
边栏推荐
- Kbp206-asemi rectifier bridge kbp206
- Difference between MotionEvent. getRawX and MotionEvent. getX
- Kubernetes -- cluster expansion principle
- 花了2晚,拿到了吴恩达@斯坦福大学的机器学习课程证书
- Flume configuration 4 - customize mysqlsource
- [learning notes] month end operation -gr/ir reorganization
- SQL performance optimization skills
- SPI and IIC communication protocol
- Redis6-01nosql database
- MySQL winter vacation self-study 2022 11 (9)
猜你喜欢

About MySQL database connection exceptions

Learning notes of raspberry pie 4B - IO communication (I2C)

Class inheritance in C #

程序员的视力怎么样? | 每日趣闻
![[an Xun cup 2019] not file upload](/img/f1/736eb5fe51c299e3152ca87895ee99.png)
[an Xun cup 2019] not file upload

Kbp206-asemi rectifier bridge kbp206
![[learning notes] month end operation -gr/ir reorganization](/img/4e/9585b7c62527beaa30a74060cb0e94.jpg)
[learning notes] month end operation -gr/ir reorganization

Leetcode42. connect rainwater

v-if VS v-show 2.0

The perfect car for successful people: BMW X7! Superior performance, excellent comfort and safety
随机推荐
How can we truncate the float64 type to a specific precision- How can we truncate float64 type to a particular precision?
Is there any way to change the height of the uinavigationbar in the storyboard without using the UINavigationController?
[groovy] string (string injection function | asBoolean | execute | minus)
问下,这个ADB mysql支持sqlserver吗?
Machine learning experiment report 1 - linear model, decision tree, neural network part
Jd.com 2: how to prevent oversold in the deduction process of commodity inventory?
Why do some programmers change careers before they are 30?
Ask, does this ADB MySQL support sqlserver?
Flume configuration 4 - customize mysqlsource
Unity implements the code of the attacked white flash (including shader)
Sqoop command
Pat grade a 1119 pre- and post order traversals (30 points)
Mongodb common commands
Anti debugging (basic principles of debugger Design & NT NP and other anti debugging principles)
[Chongqing Guangdong education] 2777t green space planning reference questions of National Open University in autumn 2018
How to make the listbox scroll automatically when adding a new item- How can I have a ListBox auto-scroll when a new item is added?
Share the newly released web application development framework based on blazor Technology
v-if VS v-show 2.0
Daily question 2 12
【无标题】