public static void EnqueueTask(object state) { CancellationToken token = (CancellationToken)state; using (DSTeckWebPushNotificationsContext db = new DSTeckWebPushNotificationsContext()) { while (!token.IsCancellationRequested) { if (enqueueSignal.WaitOne()) { int toEnqueue = 100 - deliveryQueue.Count; if (toEnqueue > 0) { // fetch some records from db to be enqueued NotificationDelivery[] deliveries = db.NotificationDeliveries .Include("Subscription") .Include("Notification") .Include("Notification.NotificationLanguages") .Include("Notification.NotificationLanguages.Language") .Where(nd => nd.Status == NotificationDeliveryStatus.Pending && DateTime.Now >= nd.StartSendingAt) .OrderBy(nd => nd.StartSendingAt) .Take(toEnqueue) .ToArray(); foreach (NotificationDelivery delivery in deliveries) { delivery.Status = NotificationDeliveryStatus.Queued; deliveryQueue.Enqueue(delivery); } if (deliveries.Length > 0) { // save Queued state, so not fetched again the next loop db.SaveChanges(); // signal the DequeueTask dequeueSignal.Set(); } else { // no more notifications, wait 5 seconds before try fetching again enqueueSignal.Reset(); enqueueTimer.Start(); } } // save any changes made by the DequeueTask // an event may be used here to know if any changes made db.SaveChanges(); } } Task.WaitAll(dequeueTasks); db.SaveChanges(); } }
public static void StartSending(CancellationToken token) { PushService.InitServices(); using (DSTeckWebPushNotificationsContext db = new DSTeckWebPushNotificationsContext()) { NotificationDelivery[] queuedDeliveries = db.NotificationDeliveries .Where(nd => nd.Status == NotificationDeliveryStatus.Queued) .ToArray(); foreach (NotificationDelivery delivery in queuedDeliveries) { delivery.Status = NotificationDeliveryStatus.Pending; } db.SaveChanges(); } enqueueSignal = new ManualResetEvent(true); dequeueSignal = new ManualResetEvent(false); enqueueTimer = new System.Timers.Timer(); enqueueTimer.Elapsed += EnqueueTimerCallback; enqueueTimer.Interval = 5000; enqueueTimer.AutoReset = false; enqueueTimer.Stop(); enqueueTask = new Task(EnqueueTask, token, TaskCreationOptions.LongRunning); enqueueTask.Start(); deliveryQueue = new ConcurrentQueue <NotificationDelivery>(); int dequeueTasksCount = 10; dequeueTasks = new Task[dequeueTasksCount]; for (int i = 0; i < dequeueTasksCount; i++) { dequeueTasks[i] = new Task(DequeueTask, token, TaskCreationOptions.LongRunning); dequeueTasks[i].Start(); } }