private void QueueNotification(INotification notification, bool countsAsRequeue = true, bool ignoreStoppingChannel = false, bool queueToFront = false)
 {
     this.lastNotificationQueueTime = DateTime.UtcNow;
     if (this.cancelTokenSource.IsCancellationRequested)
     {
         throw new ObjectDisposedException("Service", "Service has already been signaled to stop");
     }
     if (this.ServiceSettings.MaxNotificationRequeues < 0 || notification.QueuedCount <= this.ServiceSettings.MaxNotificationRequeues)
     {
         Interlocked.Increment(ref this.trackedNotificationCount);
         notification.EnqueuedTimestamp = DateTime.UtcNow;
         if (countsAsRequeue)
         {
             ++notification.QueuedCount;
         }
         if (queueToFront)
         {
             this.queuedNotifications.EnqueueAtStart(notification);
         }
         else
         {
             this.queuedNotifications.Enqueue(notification);
         }
         this.waitQueuedNotifications.Set();
     }
     else
     {
         NotificationFailedDelegate notificationFailed = this.OnNotificationFailed;
         if (notificationFailed != null)
         {
             notificationFailed((object)this, notification, (Exception) new MaxSendAttemptsReachedException());
         }
         Log.Info("Notification ReQueued Too Many Times: {0}", (object)notification.QueuedCount);
     }
 }
        private void DoChannelWork(IPushChannel channel, CancellationTokenSource cancelTokenSource)
        {
            string str = Guid.NewGuid().ToString();
            long   num = 0;

            while (!cancelTokenSource.IsCancellationRequested)
            {
                INotification notification = this.queuedNotifications.Dequeue();
                if (notification == null)
                {
                    Thread.Sleep(100);
                }
                else
                {
                    ManualResetEvent waitForNotification = (ManualResetEvent)null;
                    if (this.BlockOnMessageResult)
                    {
                        waitForNotification = new ManualResetEvent(false);
                    }
                    double totalMilliseconds = (DateTime.UtcNow - notification.EnqueuedTimestamp).TotalMilliseconds;
                    lock (this.measurementsLock)
                        this.measurements.Add(new PushServiceBase.WaitTimeMeasurement((long)totalMilliseconds));
                    DateTime sendStart = DateTime.UtcNow;
                    ++num;
                    Interlocked.Increment(ref this.totalSendCount);
                    if (num % 1000L == 0L)
                    {
                        Log.Debug("{0}> Send Count: {1} ({2})", (object)str, (object)num, (object)Interlocked.Read(ref this.totalSendCount));
                    }
                    channel.SendNotification(notification, (SendNotificationCallbackDelegate)((sender, result) =>
                    {
                        Interlocked.Decrement(ref this.trackedNotificationCount);
                        TimeSpan timeSpan = DateTime.UtcNow - sendStart;
                        lock (this.sendTimeMeasurementsLock)
                            this.sendTimeMeasurements.Add(new PushServiceBase.WaitTimeMeasurement((long)timeSpan.TotalMilliseconds));
                        waitForNotification?.Set();
                        if (result.ShouldRequeue)
                        {
                            NotificationRequeueEventArgs e = new NotificationRequeueEventArgs(result.Notification, result.Error);
                            NotificationRequeueDelegate notificationRequeue = this.OnNotificationRequeue;
                            if (notificationRequeue != null)
                            {
                                notificationRequeue((object)this, e);
                            }
                            if (e.Cancel)
                            {
                                return;
                            }
                            this.QueueNotification(result.Notification, result.CountsAsRequeue, true, true);
                        }
                        else if (!result.IsSuccess)
                        {
                            if (result.IsSubscriptionExpired)
                            {
                                if (!string.IsNullOrEmpty(result.NewSubscriptionId))
                                {
                                    DeviceSubscriptionChangedDelegate subscriptionChanged = this.OnDeviceSubscriptionChanged;
                                    if (subscriptionChanged == null)
                                    {
                                        return;
                                    }
                                    subscriptionChanged((object)this, result.OldSubscriptionId, result.NewSubscriptionId, result.Notification);
                                }
                                else
                                {
                                    DeviceSubscriptionExpiredDelegate subscriptionExpired = this.OnDeviceSubscriptionExpired;
                                    if (subscriptionExpired == null)
                                    {
                                        return;
                                    }
                                    subscriptionExpired((object)this, result.OldSubscriptionId, result.SubscriptionExpiryUtc, result.Notification);
                                }
                            }
                            else
                            {
                                NotificationFailedDelegate notificationFailed = this.OnNotificationFailed;
                                if (notificationFailed == null)
                                {
                                    return;
                                }
                                notificationFailed((object)this, result.Notification, result.Error);
                            }
                        }
                        else
                        {
                            NotificationSentDelegate notificationSent = this.OnNotificationSent;
                            if (notificationSent == null)
                            {
                                return;
                            }
                            notificationSent((object)this, result.Notification);
                        }
                    }));
                    if (waitForNotification != null && !waitForNotification.WaitOne(this.ServiceSettings.NotificationSendTimeout))
                    {
                        Interlocked.Decrement(ref this.trackedNotificationCount);
                        Log.Info("Notification send timeout");
                        NotificationFailedDelegate notificationFailed = this.OnNotificationFailed;
                        if (notificationFailed != null)
                        {
                            notificationFailed((object)this, notification, (Exception) new TimeoutException("Notification send timed out"));
                        }
                    }
                    if (waitForNotification != null)
                    {
                        waitForNotification.Close();
                        waitForNotification = (ManualResetEvent)null;
                    }
                }
            }
            channel.Dispose();
        }