/// <summary> /// Thread Run /// </summary> private void Run() { while (!(Simias.Service.Manager.ShuttingDown || killThread)) { try { int waitTime; // Get a subscription item. SubQItem qItem = DequeueSubscription(out waitTime); if (qItem != null) { bool done = false; switch (qItem.Subscription.SubscriptionState) { // invited (master) case SubscriptionStates.Invited: done = DoInvited(qItem.POBox, qItem.Subscription); break; // replied (slave) case SubscriptionStates.Replied: done = DoReplied(qItem.POBox, qItem.Subscription); break; // delivered (slave) case SubscriptionStates.Delivered: done = DoDelivered(qItem.POBox, qItem.Subscription); break; } if (!done) { // Put the item back onto the queue and process the next item // that is on the queue. qItem.ProcessTime = DateTime.Now + TimeSpan.FromSeconds(10); QueueSubscription(qItem); } } else { // Wait for an item to be placed on the queue. subEvent.WaitOne(waitTime, true); } } catch (Exception e) { log.Debug(e, "Exception in subscription thread - Ignored"); Thread.Sleep(10 * 1000); } } }
/// <summary> /// Dequeues the subscription information from the head of the queue. /// </summary> /// <param name="waitTime">The amount of time to wait before </param> /// <returns>A SubQItem object if one exists on the queue. Otherwise /// null is returned.</returns> private SubQItem DequeueSubscription(out int waitTime) { SubQItem qItem = null; waitTime = Timeout.Infinite; // Get a lock on the queue. lock (typeof(SubscriptionService)) { int nextProcessTime = Int32.MaxValue; for (int i = 0; i < subQueue.Count; ++i) { // Remove the item from the head of the queue. SubQItem tempItem = subQueue.Dequeue() as SubQItem; subTable.Remove(tempItem.Subscription.ID); // Check if this item is ready to be processed. TimeSpan ts = tempItem.ProcessTime - DateTime.Now; int tempProcessTime = Convert.ToInt32(ts.TotalMilliseconds); if (tempProcessTime <= 0) { // The item is ready to be processed. qItem = tempItem; break; } else { // This item needs to wait longer before being processed. // Put it on the tail of the queue. subQueue.Enqueue(tempItem); subTable.Add(tempItem.Subscription.ID, null); // Always take the lowest next process time. if (nextProcessTime > tempProcessTime) { nextProcessTime = tempProcessTime; } } } // If there are still entries on the queue, but none being returned, // set the wait time for the next item process time. if ((subQueue.Count > 0) && (qItem == null)) { waitTime = nextProcessTime; } } return(qItem); }
/// <summary> /// Adds subscription information to be processed if it isn't already /// being processed. /// </summary> /// <param name="qItem">A SubQItem object that will be placed on the queue.</param> /// <returns>True if the subscription was queued for processing. False /// if the subscription was already being processed.</returns> private bool QueueSubscription(SubQItem qItem) { bool exists = true; lock (typeof(SubscriptionService)) { if (!subTable.ContainsKey(qItem.Subscription.ID)) { subQueue.Enqueue(qItem); subTable.Add(qItem.Subscription.ID, null); exists = false; } } return(exists); }