174 lines
		
	
	
		
			6.2 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			174 lines
		
	
	
		
			6.2 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
#if FRAMEWORK20
 | 
						|
using System;
 | 
						|
using System.Collections.Generic;
 | 
						|
using System.Text;
 | 
						|
using Microsoft.Win32;
 | 
						|
using System.Timers;
 | 
						|
 | 
						|
namespace DevComponents.Schedule.Model
 | 
						|
{
 | 
						|
    /// <summary>
 | 
						|
    /// Provides notification support for appointments.
 | 
						|
    /// </summary>
 | 
						|
    internal static class NotificationServer
 | 
						|
    {
 | 
						|
        #region Private Variables
 | 
						|
        private static Timer _Timer = null;
 | 
						|
        internal static event NotificationServerEventHandler NotifySubscribers;
 | 
						|
        private static DateTime _NextEventTime;
 | 
						|
        private static List<NotificationRequest> _RequestList = new List<NotificationRequest>();
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region Constructor
 | 
						|
        static NotificationServer()
 | 
						|
        {
 | 
						|
            _Timer = new Timer();
 | 
						|
            _Timer.Elapsed += new ElapsedEventHandler(NotificationEventTimerTick);
 | 
						|
            SystemEvents.TimeChanged += new EventHandler(SystemEvents_TimeChanged);
 | 
						|
            _NextEventTime = DateTime.MinValue;
 | 
						|
        }
 | 
						|
 | 
						|
        static void SystemEvents_TimeChanged(object sender, EventArgs e)
 | 
						|
        {
 | 
						|
            if (_NextEventTime > DateTime.MinValue && UtcNow.Subtract(_NextEventTime).TotalSeconds <= 0)
 | 
						|
                NotifySubscribersOnTimeEvent();
 | 
						|
        }
 | 
						|
 | 
						|
        static void NotificationEventTimerTick(object sender, ElapsedEventArgs e)
 | 
						|
        {
 | 
						|
            NotifySubscribersOnTimeEvent();
 | 
						|
        }
 | 
						|
 | 
						|
        private static bool _Notifying = false;
 | 
						|
        private static void NotifySubscribersOnTimeEvent()
 | 
						|
        {
 | 
						|
            try
 | 
						|
            {
 | 
						|
                _Notifying = true;
 | 
						|
                _Timer.Stop();
 | 
						|
#if DEBUG
 | 
						|
                Console.WriteLine("{0} NotificationServer notifying subscribers count: {1}", DateTime.Now, _RequestList.Count);
 | 
						|
#endif
 | 
						|
                // Reset next notification time...
 | 
						|
                _NextEventTime = DateTime.MinValue;
 | 
						|
 | 
						|
                if (_RequestList.Count == 0)
 | 
						|
                {
 | 
						|
                    return;
 | 
						|
                }
 | 
						|
                DateTime now = CalendarModel.GetCalendarDateTime(UtcNow);
 | 
						|
                NotificationRequest[] requestList = new NotificationRequest[_RequestList.Count];
 | 
						|
                _RequestList.CopyTo(requestList);
 | 
						|
                DateTime nextNotification = DateTime.MinValue;
 | 
						|
                foreach (NotificationRequest item in requestList)
 | 
						|
                {
 | 
						|
                    if (item.NotificationTime <= now)
 | 
						|
                    {
 | 
						|
                        if (item.NotificationHandler != null)
 | 
						|
                        {
 | 
						|
                            //if (System.Threading.Thread.CurrentThread.ManagedThreadId != item.ThreadId)
 | 
						|
                            //{
 | 
						|
                                
 | 
						|
                            //    //System.Threading.SendOrPostCallback callback = new System.Threading.SendOrPostCallback(SendNotification);
 | 
						|
                            //    //System.Windows.Threading.DispatcherSynchronizationContext.Current.Post(callback, item);
 | 
						|
                            //}
 | 
						|
                            //else
 | 
						|
                                item.NotificationHandler(item, new NotificationServerEventArgs(now));
 | 
						|
                        }
 | 
						|
                        _RequestList.Remove(item);
 | 
						|
                    }
 | 
						|
                    else if (item.NotificationTime < nextNotification || nextNotification == DateTime.MinValue)
 | 
						|
                        nextNotification = item.NotificationTime;
 | 
						|
                }
 | 
						|
 | 
						|
                if (nextNotification > DateTime.MinValue)
 | 
						|
                {
 | 
						|
                    SetNextEventTime(nextNotification);
 | 
						|
                }
 | 
						|
                //else
 | 
						|
                //    Console.WriteLine("Not setting next notification time...");
 | 
						|
            }
 | 
						|
            finally
 | 
						|
            {
 | 
						|
                _Notifying = false;
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        private static void SendNotification(object e)
 | 
						|
        {
 | 
						|
            NotificationRequest item = (NotificationRequest)e;
 | 
						|
            if (item.NotificationHandler != null)
 | 
						|
            {
 | 
						|
                if (System.Threading.Thread.CurrentThread.ManagedThreadId != item.ThreadId)
 | 
						|
                {
 | 
						|
                    Console.WriteLine("Different THREAD");
 | 
						|
                }
 | 
						|
                else
 | 
						|
                {
 | 
						|
                    DateTime now = CalendarModel.GetCalendarDateTime(UtcNow);
 | 
						|
                    item.NotificationHandler(item, new NotificationServerEventArgs(now));
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
 | 
						|
        private static void SetNextEventTime(DateTime dateTime)
 | 
						|
        {
 | 
						|
            DateTime now = CalendarModel.GetCalendarDateTime(UtcNow);
 | 
						|
            if (dateTime.Subtract(now).TotalSeconds <= 0)
 | 
						|
            {
 | 
						|
                if (!_Notifying)
 | 
						|
                    NotifySubscribersOnTimeEvent();
 | 
						|
                else
 | 
						|
                    _NextEventTime = DateTime.MinValue;
 | 
						|
            }
 | 
						|
            else if (dateTime.Subtract(now).TotalSeconds > 0 && (_NextEventTime == DateTime.MinValue || dateTime < _NextEventTime))
 | 
						|
            {
 | 
						|
                double nextEvent = dateTime.Subtract(UtcNow).TotalSeconds + 1;
 | 
						|
                if (nextEvent > int.MaxValue / 1000)
 | 
						|
                    nextEvent = (int.MaxValue - 1) / 1000;
 | 
						|
                _Timer.Interval = (int)Math.Max(5, nextEvent * 1000);
 | 
						|
#if DEBUG
 | 
						|
                Console.WriteLine("{0} NotificationServer scheduling next event on: {1}, previous scheduled event on: {2}", DateTime.Now, dateTime, _NextEventTime);
 | 
						|
#endif
 | 
						|
                _Timer.Start();
 | 
						|
                _NextEventTime = dateTime;
 | 
						|
            }
 | 
						|
            //else
 | 
						|
            //    _NextEventTime = DateTime.MinValue;
 | 
						|
        }
 | 
						|
 | 
						|
        private static DateTime UtcNow
 | 
						|
        {
 | 
						|
            get
 | 
						|
            {
 | 
						|
                return TimeZoneInfo.ConvertTimeToUtc(CalendarModel.CurrentDateTime);
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        public static void UpdateNotification(NotificationRequest request)
 | 
						|
        {
 | 
						|
            SetNextEventTime(request.NotificationTime);
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region Internal Implementation
 | 
						|
        public static void Register(NotificationRequest request)
 | 
						|
        {
 | 
						|
            _RequestList.Add(request);
 | 
						|
            SetNextEventTime(request.NotificationTime);
 | 
						|
        }
 | 
						|
 | 
						|
        public static void Unregister(NotificationRequest request)
 | 
						|
        {
 | 
						|
            _RequestList.Remove(request);
 | 
						|
        }
 | 
						|
        #endregion
 | 
						|
    }
 | 
						|
 | 
						|
    internal delegate void NotificationServerEventHandler(NotificationRequest sender, NotificationServerEventArgs e);
 | 
						|
}
 | 
						|
#endif
 | 
						|
 |