using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using JWH; using TIBCO.Rendezvous; namespace JWH.TIB { public class ListenerInfo : IDisposable { public static int NextID = 1; #region [ Event ] ===================================================== public delegate void OnReceivedHandler(ListenerInfo sender, MessageReceivedEventArgs args); public delegate void OnEventHandler(ListenerInfo sender, TibRendezvousEventArgs args); public event OnReceivedHandler OnReceivedMessage; public event OnEventHandler OnReceivedEvent; #endregion #region [ Properties ] ================================================ public int ID { get; protected set; } = 0; public XLogger Logger { get; set; } = XLogger.Instance; public string Name { get; set; } = string.Empty; public string Subject { get; set; } = string.Empty; public Listener Listener { get; set; } = null; public Queue Queue { get { return this?.Listener?.Queue; } } protected Dispatcher Dispatcher { get; set; } = null; protected Thread QueueDispatchThread { get; set; } = null; protected bool QueueDispatchFlag { get; set; } = false; protected double DispatchInterval { get; set; } = -1; #endregion #region [ Constructor ] =============================================== public ListenerInfo() { this.ID = NextID++; } ~ListenerInfo() { this.Dispose(); } public void Dispose() { try { if (this.Dispatcher != null) { this.Dispatcher.Destroy(); this.Dispatcher = null; } if (this.QueueDispatchThread != null) { this.QueueDispatchFlag = false; if (this.QueueDispatchThread.ThreadState != ThreadState.Stopped) this.QueueDispatchThread.Abort(); this.QueueDispatchThread = null; } if (this.Listener != null) { this.Listener.Destroy(); this.Listener = null; } } catch (Exception ex) { this.Logger.Fatal(ex); throw ex; } } #endregion #region [ Method ] ==================================================== protected void Raise_ReceivedData(MessageReceivedEventArgs args) { this.OnReceivedMessage?.Invoke(this, args); } protected void Raise_ReceivedEvent(TibRendezvousEventArgs args) { this.OnReceivedEvent?.Invoke(this, args); } /// /// 비정상 종료시, 내부 쓰레드가 종료되지 않는다. /// /// public bool Dispatch() { try { if (this.Listener == null) return false; if (this.Listener.Queue == null) return false; if (this.QueueDispatchThread != null) return false; this.Dispatcher = new Dispatcher(this.Listener.Queue); return true; } catch (Exception ex) { throw ex; } } /// /// Queue.Dispatch() or Queue.TimedDispatch(interval) /// /// /// public bool QueueDispatch(double interval = -1) { try { if (this.Listener == null) return false; if (this.Listener.Queue == null) return false; if (this.Dispatcher != null) return false; this.DispatchInterval = interval; if (this.QueueDispatchThread != null) this.QueueDispatchThread.Abort(); this.QueueDispatchThread = new Thread(new ThreadStart(this.QueueDispatch_Threading)); this.QueueDispatchThread.IsBackground = true; this.QueueDispatchThread.Start(); return true; } catch (Exception ex) { throw ex; } } protected void QueueDispatch_Threading() { try { this.Logger.Debug($"Start {this.Subject}"); this.QueueDispatchFlag = true; while (this.QueueDispatchFlag) { try { if (this.DispatchInterval > 0) this.Queue.TimedDispatch(this.DispatchInterval); else this.Queue.Dispatch(); //this.Logger.Info($"Queue.Count is {this.Queue.Count}"); } catch (RendezvousException ex) { this.Logger.Fatal(ex); } catch (Exception ex) { this.Logger.Fatal(ex); } } this.QueueDispatchFlag = false; this.QueueDispatchThread = null; this.Logger.Debug($"Finish"); } catch (Exception ex) { // Tread Exception...! throw ex; } } public virtual void ReceivedMessage(object sender, MessageReceivedEventArgs eventArgs) { this.Raise_ReceivedData(eventArgs); } #endregion } public class TibRendezvousEventArgs : EventArgs { public Message Message { get; private set; } = null; public string SendSubject { get; private set; } = string.Empty; public string ReplySubject { get; private set; } = string.Empty; public string Class { get; private set; } = string.Empty; public string Source { get; private set; } = string.Empty; public string Name { get; private set; } = string.Empty; public Dictionary Properties { get; private set; } = new Dictionary(); public TibRendezvousEventArgs() { } public TibRendezvousEventArgs(Message message) { this.Message = message; this.SendSubject = message.SendSubject; this.ReplySubject = message.ReplySubject; for (uint i = 0; i < message.FieldCount; i++) { MessageField field = message.GetFieldByIndex(i); if (string.Compare(field.Name, "ADV_CLASS", true) == 0) { this.Class = field.Value.ToString(); continue; } if (string.Compare(field.Name, "ADV_SOURCE", true) == 0) { this.Source = field.Value.ToString(); continue; } if (string.Compare(field.Name, "ADV_NAME", true) == 0) { this.Name = field.Value.ToString(); continue; } if (field.Value?.GetType() == typeof(DateTime)) { DateTime dt = (DateTime)field.Value; if (dt.Kind != DateTimeKind.Local) { TimeZoneInfo localZone = TimeZoneInfo.Local; DateTime localTime = TimeZoneInfo.ConvertTimeFromUtc(dt, TimeZoneInfo.Local); this.Properties[field.Name] = localTime; continue; } } this.Properties[field.Name] = field.Value; } } public override string ToString() { StringBuilder sb = new StringBuilder(); //sb.Append($"[{this.SendSubject}] "); //if (!string.IsNullOrEmpty(this.ReplySubject)) sb.Append($"From {this.ReplySubject}: "); //sb.AppendLine(); sb.Append($"ADV_CLASS='{this.Class}' "); sb.Append($"ADV_SOURCE='{this.Source}' "); sb.Append($"ADV_NAME='{this.Name}' "); foreach (KeyValuePair pair in this.Properties) sb.Append($"({pair.Value?.GetType().Name}){pair.Key}='{pair.Value?.ToString()}' "); return sb.ToString(); } } }