| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420 | using log4net;using System;using System.Collections.Generic;using System.Threading;namespace OpenSEMI.Core.Msg{	public class MsgPool	{		internal class Msg		{			public string id			{				get;				private set;			}			public string Description			{				get;				set;			}			public Action<MsgPool, object> Handler			{				get;				set;			}			public Action<MsgPool, object, object> WithParameterHandler			{				get;				set;			}			public object Sender			{				get;				private set;			}			public object Param			{				get;				private set;			}			public bool HasParam			{				get;				private set;			}			public Msg()			{				id = Guid.NewGuid().ToString();			}			public Msg(Action<MsgPool, object> handler = null, object sender = null, string desc = null)				: this()			{				id = Guid.NewGuid().ToString();				Sender = sender;				Handler = handler;				Description = desc;				HasParam = false;			}			public Msg(Action<MsgPool, object, object> handler = null, object param = null, object sender = null, string desc = null)				: this()			{				id = Guid.NewGuid().ToString();				Sender = sender;				WithParameterHandler = handler;				Description = desc;				Param = param;				HasParam = true;			}		}		private ManualResetEvent waitevent = new ManualResetEvent(false);		private Thread context;		private Action<MsgPool> Handler = null;		private Queue<Msg> PostMsgs = new Queue<Msg>();		private Stack<Msg> SendMsgs = new Stack<Msg>();		private readonly object lockMsg = new object();		private readonly object lockSubscribers = new object();		private MsgPool lazylooper;		private bool LazySupported;		private static object _lock = new object();		private static List<MsgPool> Loopers = new List<MsgPool>();		private ILog log;		private uint lastInvervalTime;		public string LooperName		{			get;			set;		}		public bool IsRuning		{			get;			private set;		}		public Dictionary<string, string> ExecutionResults		{			get;			private set;		}		public int Interval		{			get;			set;		}		public MsgPool(string loopname = null, bool lazySupported = false)		{			Interval = 500;			LazySupported = lazySupported;			ExecutionResults = new Dictionary<string, string>();			LooperName = loopname;		}		public MsgPool(int interval, Action<MsgPool> handler, string loopername = null, bool lazySupported = false)			: this(loopername, lazySupported)		{			Interval = interval;			Handler = handler;			LazySupported = lazySupported;		}		public void SetLog(ILog _log)		{			log = _log;		}		public int getCount()		{			return PostMsgs.Count + SendMsgs.Count;		}		public void Run()		{			if (!IsRuning)			{				IsRuning = true;				if (LazySupported)				{					lazylooper = new MsgPool(null, false);					lazylooper.Run();				}				context = new Thread(Loop);				context.Start();				lock (_lock)				{					Loopers.Add(this);				}			}		}		private void Loop()		{			lastInvervalTime = GetTickCount();			while (true)			{				uint millisecondsTimeout = (uint)(((uint)Interval <= GetElapsedMS(lastInvervalTime)) ? 1 : (Interval - (int)GetElapsedMS(lastInvervalTime)));				if (IsRuning)				{					bool flag = waitevent.WaitOne((int)millisecondsTimeout);					if (IsRuning)					{						if (flag)						{							Msg msg = null;							lock (lockMsg)							{								if (SendMsgs.Count > 0)								{									msg = SendMsgs.Pop();								}								else if (PostMsgs.Count > 0)								{									msg = PostMsgs.Dequeue();								}							}							if (msg != null)							{								try								{									if (!msg.HasParam && msg.Handler != null)									{										msg.Handler(this, msg.Sender);									}									else if (msg.WithParameterHandler != null)									{										msg.WithParameterHandler(this, msg.Param, msg.Sender);									}								}								catch (Exception ex)								{									ExecutionResults.Add(msg.id, ex.Message);									if (log != null)									{										log.Error("Msg:" + ex.Message + ",CallStack:" + ex.StackTrace);									}								}							}							if (SendMsgs.Count <= 0 && PostMsgs.Count <= 0)							{								waitevent.Reset();							}						}						else						{							if (Handler != null)							{								Handler(this);							}							lastInvervalTime = GetTickCount();						}						continue;					}				}				break;			}		}		public void Terminate(bool force = false)		{			if (!force)			{				if (LazySupported)				{					LazyMsg(delegate					{						lazylooper.IsRuning = false;					}, this, "Terminate lazy looper");					lazylooper.context.Join();				}				PostMsg(delegate				{					IsRuning = false;				}, this, "Terminate looper");			}			else			{				if (LazySupported)				{					lazylooper.IsRuning = false;					lazylooper.waitevent.Set();				}				IsRuning = false;				waitevent.Set();			}			lock (_lock)			{				Loopers.Remove(this);			}		}		public static void TerminateAll(bool force = false, MsgPool looper = null)		{			lock (_lock)			{				if (looper != null)				{					looper.Terminate(force);				}				else				{					foreach (MsgPool looper2 in Loopers)					{						if (!force)						{							if (looper2.LazySupported)							{								looper2.LazyMsg(delegate								{									looper2.lazylooper.IsRuning = false;								}, looper2, "Terminate lazy looper");							}							looper2.PostMsg(delegate							{								looper2.IsRuning = false;							}, looper2, "Terminate looper");						}						else						{							if (looper2.LazySupported)							{								looper2.lazylooper.IsRuning = false;								looper2.lazylooper.waitevent.Set();							}							looper2.IsRuning = false;							looper2.waitevent.Set();						}					}					Loopers.Clear();				}			}		}		public string PostMsg(Action<MsgPool, object> handler, object sender = null, string description = "handler")		{			lock (lockMsg)			{				if (!IsRuning)				{					return string.Empty;				}				Msg msg = new Msg(handler, sender, description);				PostMsgs.Enqueue(msg);				waitevent.Set();				return msg.id;			}		}		public string PostMsg(Action<MsgPool, object, object> handler, object param, object sender = null, string description = "handler")		{			lock (lockMsg)			{				if (!IsRuning)				{					return string.Empty;				}				Msg msg = new Msg(handler, param, sender, description);				PostMsgs.Enqueue(msg);				waitevent.Set();				return msg.id;			}		}		public string SendMsg(Action<MsgPool, object> handler, object sender = null, string description = "handler")		{			lock (lockMsg)			{				if (!IsRuning)				{					return string.Empty;				}				Msg msg = new Msg(handler, sender, description);				SendMsgs.Push(msg);				waitevent.Set();				return msg.id;			}		}		public string SendMsg(Action<MsgPool, object, object> handler, object param, object sender = null, string description = "handler")		{			lock (lockMsg)			{				if (!IsRuning)				{					return string.Empty;				}				Msg msg = new Msg(handler, param, sender, description);				SendMsgs.Push(msg);				waitevent.Set();				return msg.id;			}		}		public string LazyMsg(Action<MsgPool, object> handler, object sender = null, string description = "handler")		{			if (!IsRuning)			{				return string.Empty;			}			if (LazySupported)			{				return lazylooper.PostMsg(handler, sender, description);			}			return null;		}		public string LazyMsg(Action<MsgPool, object, object> handler, object param, object sender = null, string description = "handler")		{			if (!IsRuning)			{				return string.Empty;			}			if (LazySupported)			{				return lazylooper.PostMsg(handler, param, sender, description);			}			return null;		}		private uint GetElapsedMS(uint startMS)		{			uint tickCount = GetTickCount();			if (startMS > tickCount)			{				return (uint)(-1 - (int)startMS + (int)tickCount + 1);			}			return tickCount - startMS;		}		private uint GetTickCount()		{			return (uint)Environment.TickCount;		}	}}
 |