DotNet(C#)实现事件远程注册和触发

来源:互联网 发布:禁止软件联网win10 编辑:程序博客网 时间:2024/06/09 20:10


背景:
以前做过一套分布式任务管理架构来为某网站提供数据计算服务,
该网站每次数据计算可以分解为几百个小任务进行,而每个任务可能需要访问的数据量很大,
所以系统有一个管理平台,用来显示系统的运行状态,或某类计算节点的运行压力,
用户也可以在平台上执行一些管理功能,为了应对平台上频繁的功能追加,在系统核心模块
添加了事件处理模块,每当用户需要在平台添加某个功能,只需要开发对应功能的一个功能模块,
该功能模块只需要在事件处理注册一个事件,即可执行执行来自平台的命令需求。该模块可发布在
局域网内的任何一台机器上。

下面看代码, 临时写的,简化或省略了其中的数据部分,省略了系统定义的事件树,没有注释-_-!!

多个模块可重复注册同一种事件,如模块自检

 

先定义一个事件容器:

 

[Serializable]    public class EventHandlerSet : IDisposable    {        protected System.Collections.Hashtable events = new System.Collections.Hashtable();        // indexer        public virtual Delegate this[object eventKey]        {            get { return (Delegate)events[eventKey]; }            set { events[eventKey] = value; }        }        public virtual void AddHandler(object eventKey, Delegate handler)        {            events[eventKey] = Delegate.Combine((Delegate)events[eventKey], handler);        }        public virtual void RemoveHandler(object eventKey)        {            events.Remove(eventKey);        }        public virtual void RemoveHandler(object eventKey, Delegate handler)        {            events[eventKey] = Delegate.Remove((Delegate)events[eventKey], handler);        }        // fire event        public virtual void Fire(object eventKey, TaskEventArgs args)        {            if (!events.ContainsKey(eventKey))            {                return;            }            Delegate handler = (Delegate)events[eventKey];            if (handler != null)            {                handler.DynamicInvoke(new object[] { eventKey, args });            }        }        // Synchronized        public static EventHandlerSet Synchronized(EventHandlerSet eventHandlerSet)        {            if (eventHandlerSet == null)            {                throw new Exception();            }            return new SynchronizedEventHandlerSet(eventHandlerSet);        }        public void Dispose()        {            events.Clear();        }    }


线程安全:

public delegate void TaskEventHandler(TaskEventArgs args);[Serializable]    public class SynchronizedEventHandlerSet : EventHandlerSet    {        private EventHandlerSet eventHandlerSet;        public SynchronizedEventHandlerSet(EventHandlerSet eventHandlerSet)        {            this.eventHandlerSet = eventHandlerSet;            Dispose();        }        // indexer        public override Delegate this[object eventKey]        {            [MethodImpl(MethodImplOptions.Synchronized)]            get { return eventHandlerSet[eventKey]; }            [MethodImpl(MethodImplOptions.Synchronized)]            set { eventHandlerSet[eventKey] = value; }        }        [MethodImpl(MethodImplOptions.Synchronized)]        public override void AddHandler(object eventKey, Delegate handler)        {            eventHandlerSet.AddHandler(eventKey, handler);        }        [MethodImpl(MethodImplOptions.Synchronized)]        public override void RemoveHandler(object eventKey)        {            eventHandlerSet.RemoveHandler(eventKey);        }        [MethodImpl(MethodImplOptions.Synchronized)]        public override void RemoveHandler(object eventKey, Delegate handler)        {            eventHandlerSet.RemoveHandler(eventKey, handler);        }        [MethodImpl(MethodImplOptions.Synchronized)]        public override void Fire(object eventKey, TaskEventArgs args)        {            eventHandlerSet.Fire(eventKey, args);        }        [MethodImpl(MethodImplOptions.Synchronized)]        public override void FireEx(object eventKey, TaskEventArgs args)        {            eventHandlerSet.FireEx(eventKey, args);        }    }

 

事件参数类:

[Serializable]    public class TaskEventArgs : EventArgs    {        public object Args { get; set; }        public TaskEventArgs()        {        }        public TaskEventArgs(object args)        {            this.Args = args;        }    }


 

事件封送类,事件分为两类,定时触发(TimerEvent)和条件触发(CommandEvent):

public class EventProvider : MarshalByRefObject    {        private EventHandlerSet events = null;        private TimerEventHandler timerHandler = null;        private CommandEventHandler cmdHandler = null;        private UnRegisterEventHandler unregisterHandler = null;        public EventProvider()        {            events = EventHandlerSet.Synchronized(new EventHandlerSet());        }        public void Fire(object key, TaskEventArgs args)        {            events.Fire(key, args);        }        #region Interface Method        public void RegisterTimerEvent(string strName, int nInterval, object key, FireHandler fh)        {            events.AddHandler(key, fh);            timerHandler(strName, nInterval, key);        }        public void RegisterCommandEvent(string strName, object key, FireHandler fh)        {            events.AddHandler(key, fh);            cmdHandler(strName, key);        }        public void UnRegisterEvent(string strName, object key)        {            events.RemoveHandler(key);            unregisterHandler(strName, key);        }        #endregion        public override object InitializeLifetimeService()        {            return null;        }        #region Register Callback        public void RegisterTimerEventHandler(TimerEventHandler teh)        {            timerHandler += teh;        }        public void RegisterCommandEventHandler(CommandEventHandler ceh)        {            cmdHandler += ceh;        }        public void RegisterUnRegisterEventHandler(UnRegisterEventHandler ueh)        {            unregisterHandler += ueh;        }        #endregion    }


因为远程支持,添加事件封送的代理类,功能模块在此处注册事件:

/// <summary>    /// 事件控制器实体代理类    /// Client端在此处注册事件,Fire函数委托给封送类触发    /// </summary>    public class EventProviderWrapper : MarshalByRefObject    {        private EventHandlerSet events = null;        private IRemotingClient client = null;        private Dictionary<string, object> runtime = null;        public EventProviderWrapper(int nPort)        {            events = EventHandlerSet.Synchronized(new EventHandlerSet());            runtime = new Dictionary<string, object>();            client = new RemotingProvider(nPort);            client.ClientStart();        }        public void Fire(object key, TaskEventArgs tea)        {            events.Fire(key, tea);        }        #region register event        public void RegisterTimerEvent(string strName, int nInterval, TaskEventHandler teh)        {            if (runtime.ContainsKey(strName))            {                return;            }            object key = CreateKey();            events.AddHandler(key, teh);            runtime.Add(strName, key);            client.RegisterTimerEvent(strName, nInterval, key, this.Fire);        }        public void RegisterCommandEvent(string strName, TaskEventHandler teh)        {            if (runtime.ContainsKey(strName))            {                // 此事件已经注册                return;            }            object key = CreateKey();            events.AddHandler(key, teh);            runtime.Add(strName, key);            client.RegisterCommandEvent(strName, key, this.Fire);        }        public void UnRegisterEvent(string strName)        {            if (!runtime.ContainsKey(strName))            {                // 此事件已经注册                return;            }            events.RemoveHandler(runtime[strName]);            client.UnRegisterEvent(strName, runtime[strName]);            runtime.Remove(strName);        }        public void Dispose()        {            foreach (string key in runtime.Keys)            {                events.RemoveHandler(runtime[key]);                client.UnRegisterEvent(key, runtime[key]);            }            runtime.Clear();        }        #endregion        public override object InitializeLifetimeService()        {            return null;        }        private object CreateKey()        {            return Guid.NewGuid();        }    }


Remoting处理,为了简化将Client和Server合到了一起:

    public interface IRemotingClient    {        bool ClientStart();        void RegisterTimerEvent(string strName, int nInterval, object key, FireHandler fh);        void RegisterCommandEvent(string strName, object key, FireHandler fh);        void UnRegisterEvent(string strName, object key);    }    public interface IRemotingServer    {        bool ServerStart(TimerEventHandler teh, CommandEventHandler ceh, UnRegisterEventHandler ueh);        bool Fire(object key, TaskEventArgs args);    }public class RemotingProvider : IRemotingServer, IRemotingClient    {        private const string URL = "eventcontroller.soap";        private EventProvider provider = null;        private string strIp = "localhost";        private int nPort = 0;        public RemotingProvider(int port)        {            this.nPort = port;        }        public RemotingProvider(string ip, int port)            : this(port)        {            this.strIp = ip;        }        #region IRemotingServer        public bool ServerStart(TimerEventHandler teh, CommandEventHandler ceh, UnRegisterEventHandler ueh)        {            BinaryServerFormatterSinkProvider serverProvider = new BinaryServerFormatterSinkProvider();            BinaryClientFormatterSinkProvider clientProvider = new BinaryClientFormatterSinkProvider();            serverProvider.TypeFilterLevel = TypeFilterLevel.Full;            IDictionary prots = new Hashtable();            prots["name"] = "remoting";            prots["port"] = nPort;            try            {                HttpChannel channel = new HttpChannel(prots, clientProvider, serverProvider);                ChannelServices.RegisterChannel(channel);                provider = new EventProvider();                provider.RegisterTimerEventHandler(teh);                provider.RegisterCommandEventHandler(ceh);                provider.RegisterUnRegisterEventHandler(ueh);                ObjRef objRef = RemotingServices.Marshal(provider, URL);            }            catch            {                return false;            }            return true;        }        public bool Fire(object key, TaskEventArgs args)        {            try            {                provider.Fire(key, args);            }            catch            {                return false;            }            return true;        }        #endregion        #region IRemotingClient        public bool ClientStart()        {            BinaryServerFormatterSinkProvider serverProvider = new BinaryServerFormatterSinkProvider();            BinaryClientFormatterSinkProvider clientProvider = new BinaryClientFormatterSinkProvider();            serverProvider.TypeFilterLevel = TypeFilterLevel.Full;            IDictionary ports = new Hashtable();            ports["port"] = 0;            HttpChannel channel = new HttpChannel(ports, clientProvider, serverProvider);            try            {                ChannelServices.RegisterChannel(channel);            }            catch            {            }            try            {                string strAddr = string.Format("http://{0}:{1}/{2}", strIp, nPort, URL);                provider = (EventProvider)Activator.GetObject(typeof(EventProvider), strAddr);            }            catch            {                return false;            }            return true;        }        public void RegisterTimerEvent(string strName, int nInterval, object key, FireHandler fh)        {            provider.RegisterTimerEvent(strName, nInterval, key, fh);        }        public void RegisterCommandEvent(string strName, object key, FireHandler fh)        {            provider.RegisterCommandEvent(strName, key, fh);        }        public void UnRegisterEvent(string strName, object key)        {            provider.UnRegisterEvent(strName, key);        }        #endregion    }


 

核心端事件管理类:

public class EventInfo : IDisposable    {        public object Key { get; private set; }        public string Name { get; private set; }        public int Interval { get; private set; }        private Timer runTimer = null;        private FireHandler fireHandler = null;        public EventInfo(object key, string strName)        {            this.Key = key;            this.Name = strName;        }        public EventInfo(object key, string strName, int nInterval, FireHandler fh)            : this(key, strName)        {            this.Interval = nInterval;            fireHandler += fh;            runTimer = new Timer();            runTimer.Interval = nInterval;            runTimer.Elapsed += new ElapsedEventHandler(runTimer_Elapsed);            runTimer.Start();        }        void runTimer_Elapsed(object sender, ElapsedEventArgs e)        {            TaskEventArgs args = new TaskEventArgs();            fireHandler(this.Key, args);        }        public void Dispose()        {            if (runTimer != null)            {                runTimer.Stop();            }        }    }


事件控制器:

        public class EventController : IDisposable    {        private IRemotingServer server = null;        public Dictionary<string, List<EventInfo>> listEvent = null;        public EventController(int nPort)        {            listEvent = new Dictionary<string, List<EventInfo>>();            server = new RemotingProvider(nPort);            server.ServerStart(this.OnRegisterTimerEvent, this.OnRegisterCommandEvent, this.OnUnRegisterEvent);        }        #region Inner Register        #endregion        #region Execute        public void ExecuteCommand(IManagementMessage command)        {            if (!listEvent.ContainsKey(command.MessageCode))            {                return;            }            List<EventInfo> listTmp = listEvent[command.MessageCode];            foreach (EventInfo item in listTmp)            {                TaskEventArgs args = new TaskEventArgs(command);                server.Fire(item.Key, args);            }        }        private void OnTimerFire(object key, TaskEventArgs e)        {            try            {                server.Fire(key, e);            }            catch            {            }        }        #endregion        public void Dispose()        {            foreach (string strName in listEvent.Keys)            {                List<EventInfo> listTmp = listEvent[strName];                foreach (EventInfo item in listTmp)                {                    item.Dispose();                }                listTmp.Clear();            }            listEvent.Clear();        }        #region Component Register        private void OnRegisterTimerEvent(string strName, int nInterval, object key)        {            EventInfo item = new EventInfo(key, strName, nInterval, this.OnTimerFire);            List<EventInfo> listTmp = null;            if (!listEvent.ContainsKey(strName))            {                listTmp = new List<EventInfo>();                listTmp.Add(item);                listEvent.Add(strName, listTmp);            }            else            {                listEvent[strName].Add(item);            }                    }        private void OnRegisterCommandEvent(string strName, object key)        {            EventInfo item = new EventInfo(key, strName);            List<EventInfo> listTmp = null;            if (!listEvent.ContainsKey(strName))            {                listTmp = new List<EventInfo>();                listTmp.Add(item);                listEvent.Add(strName, listTmp);            }            else            {                listEvent[strName].Add(item);            }                    }        private void OnUnRegisterEvent(string strName, object key)        {            if (!listEvent.ContainsKey(strName))            {                return;            }            EventInfo item = listEvent[strName].Find(                delegate(EventInfo ev)                {                    return ev.Key == key;                });            if (item == null)            {                return;            }            item.Dispose();            listEvent[strName].Remove(item);        }        #endregion            }


功能端事件注册方法:

EventProviderWrapper wrapper = new EventProviderWrapper(nPort); // nPort为事件发布端口// Defines.CODE_SYSTEM_REPORT 为系统定义的事件Key, 非必需// 注册一个事件wrapper.RegisterCommandEvent(Defines.CODE_SYSTEM_REPORT, this.Invoke);


 

原创粉丝点击