Scene
There is a scenario, a mail alert for the Windows service that gets all the users who turn on mailtips, loops over the messages of those users, and sends a service number message. But the problem comes, the user is less than the case, polling time can endure, if the user is more, the user name sorted by the people, receive email reminders message, delay time is very long.
Get ready
C # Redis Practice list,hashtable
Redis Queue of C #
Scheme
1, the producer thread one gets all the users who open the email alert.
2, according to the configuration to determine the number of queues to use, and the capacity of each queue.
3, line Cheng, get the queue is not full, the current user is enqueued. If all the queues are full, suspend 2s, and then regain the queue that is not full, and the user is queued.
4, according to the configuration to open the consumer thread, each thread independent processing logic. Suspends 2s if the obtained user is empty or the current queue is empty. Otherwise, the user's message is pulled through the EWS service, and a reminder is taken.
5. If an error occurs during the acquisition of a user's message, the user is re-entered into the current queue, waiting for the next pull.
Test
Queue
Test code
/// <summary> ///Message Queuing Management/// </summary> Public classmyredisqueuebus:idisposable {/// <summary> ///Number of Threads/// </summary> Private int_threadcount; /// <summary> ///the capacity of Itcode in each thread/// </summary> Private int_threadcapacity; /// <summary> ///Threads/// </summary> Privatethread[] _threads; /// <summary> ///Producer Threads/// </summary> PrivateThread _producerthread; /// <summary> ///Suspend Time/// </summary> Private Const intWaitseconde = -; /// <summary> ///Queue name Prefix/// </summary> Private string_queueprefix; /// <summary> ///constructor Function/// </summary> /// <param name= "ThreadCount" >Number of Threads</param> /// <param name= "threadcapacity" >queue capacity processed per thread</param> /// <param name= "Queueprefix" >queue capacity processed per thread</param> PublicMyredisqueuebus (intThreadCount,intThreadcapacity,stringQueueprefix) { This. _threadcapacity =threadcapacity; This. _threadcount =ThreadCount; This. _queueprefix = Queueprefix +"_{0}"; } /// <summary> ///Open producer/// </summary> Public voidStartproducer () {_producerthread=NewThread (() ={iredisclientfactory Factory=redisclientfactory.instance; Emailalertsdata Emailalertsdata=NewEmailalertsdata (); //White list string[] Useridswhitearray = TaskGloableParameter.WhiteList.Split (New Char[] {',',',' },
Stringsplitoptions.removeemptyentries); while(true) { //get all users who have email alerts turned onList<emailalerts> lstemails =emailalertsdata.getallstartalerts (Useridswhitearray); //Queue using(Iredisclient client =Factory. Createredisclient (Webconfig.redisserver, Webconfig.redisport)) {client. Password=webconfig.redispwd; Client. Db=Webconfig.redisserverdb; foreach(varIteminchlstemails) { intQueueindex =-1; stringQueueName =string. Format ( This. _queueprefix, Queueindex); for(inti =0; i < _threadcount; i++) {QueueName=string. Format ( This. _queueprefix, i); //If the current queue is not filled, jump out and use the queue to Enqueue if(Client. GetListCount (QueueName) <_threadcapacity) {Queueindex=i; Break; } } //If all the queues are full, suspend 2s wait for the consumer to consume a portion of the data and start over again if(Queueindex = =-1) {thread.spinwait (Waitseconde); //re-fetch queue for(inti =0; i < _threadcount; i++) {QueueName=string. Format ( This. _queueprefix, i); //If the current queue is not filled, jump out and use the queue to Enqueue if(Client. GetListCount (QueueName) <_threadcapacity) {Queueindex=i; Break; } } } Else { //QueueClient. Enqueueitemonlist (QueueName, Jsonconvert.serializeobject (NewMyqueueitem {UserId=Item.itcode, Syncstate=item. Email_syncstate})); } } } } }); _producerthread.start (); } /// <summary> ///Open Consumer/// </summary> Public voidStartcustomer () {_threads=NewThread[_threadcount]; for(inti =0; I < _threads. Length; i++) {_threads[i]=NewThread (Customerrun); _threads[i]. Start (i); } } Private voidCustomerrun (Objectobj) { intThreadindex =Convert.ToInt32 (obj); stringQueueName =string. Format ( This. _queueprefix, Threadindex); Iredisclientfactory Factory=redisclientfactory.instance; while(true) { using(Iredisclient client =Factory. Createredisclient (Webconfig.redisserver, Webconfig.redisport)) {client. Password=webconfig.redispwd; Client. Db=Webconfig.redisserverdb; if(Client. GetListCount (QueueName) >0) { stringResultjson =client. Dequeueitemfromlist (QueueName); //suspend 2s If the obtained result is empty if(string. IsNullOrEmpty (Resultjson)) {thread.spinwait (Waitseconde); } Else { Try { //time consuming business processingMyqueueitem item = jsonconvert.deserializeobject<myqueueitem>(Resultjson); Console.WriteLine ("Threadid:{0},user:{1}", Thread.CurrentThread.ManagedThreadId.ToString (), item. USERID); } Catch(Exception ex) {//If an error occurs, re-queueclient. Enqueueitemonlist (QueueName, Resultjson); } } } Else { //the current queue is empty, hangs 2sthread.spinwait (Waitseconde); } } } } Public voidDispose () {//destroying a thread when releasing resources if( This. _threads! =NULL) { for(inti =0; I < This. _threads. Length; i++) { This. _threads[i]. Abort (); }} GC. Collect (); } }
Main method call
Static void Main (string[] args) { new Myredisqueuebus (ten ) Mail_reminder_queue " ); Bus. Startproducer (); Thread.spinwait (+); Bus. Startcustomer (); Console.read (); }
Summarize
By configuration, determine the number of open queues and the number of threads, if the user increases can increase the number of threads, or add a machine to resolve. In this way, you can solve the post-ranked users, through the random distribution queue, have the opportunity to get email reminders in advance, you can shorten the delay time of email reminders. Of course, such a scheme is not perfect, and can only be thought of here now. This idea is written here, and it is hoped to get a better solution.
The Redis queue for C # is used in email reminders