Click here to Skip to main content
15,892,059 members
Articles / Programming Languages / C#

Client Server Event Subscription Techniques in C#

Rate me:
Please Sign up or sign in to vote.
4.97/5 (13 votes)
18 Sep 2012CPOL10 min read 51K   2.2K   47  
This article notes down few essential techniques, their detailed implementation with advantages and disadvantages.
/// Author - anshu.dutta@gmail.com ///
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Collections;

namespace Demo.Events.ManualResetEvent
{
    class Program
    {
        static void Main(string[] args)
        {
            Server s = new Server();
            WaitHandler.TaskList = new List<object>();

            List<Client> c = new List<Client>()
            {
                new Client(1),
                new Client(2),
                new Client(3)
            };

            while (true)
            {
                //Thread.Sleep(new Random().Next(20) * 1000);
                Thread.Sleep(1000);
                int eventID = new Random().Next(500);
                //Console.WriteLine("Event ID generated - {0}", eventID);
                //WaitHandler.TaskId = eventID;
                //Console.WriteLine("Server Generating event {0} @ {1}",eventID, DateTime.Now.ToString("hh:mm:ss"));
                //s.DoWork(eventID);
                s.RegisterEvent(new ServerEvent() { EventID = eventID });
            }
        }

    }

    public class ServerEvent
    {
        public int EventID { get; set; }
    }

    public class Server
    {
        public Queue EventQueue { get; set; }
        private static object syncLock = new object();

        public Server() 
        {
            EventQueue = new Queue();
            Task.Factory.StartNew(()=> {this.ManageEvents();});
        }

        public void RegisterEvent(ServerEvent e)
        {
            lock (syncLock)
            {
                EventQueue.Enqueue(e);
            }
            
        }

        private void ManageEvents()
        {
            
            while (true)
            {
                if (this.EventQueue!=null && this.EventQueue.Count>0)
                {
                    if (!WaitHandler.GetManualEventHandler().WaitOne(0))
                    {
                        // Handle is reset - No events are currently being processed

                        int eventID = ((ServerEvent)this.EventQueue.Peek()).EventID;
                        if (this.EventQueue.Count > 1)
                        {
                            // remove the event that hass been processed
                            lock (syncLock)
                            {
                                this.EventQueue.Dequeue();
                            }
                            
                            Console.WriteLine("Server Unregistering event {0} @ {1}", eventID, DateTime.Now.ToString("hh:mm:ss"));
                        }

                        eventID = ((ServerEvent)this.EventQueue.Peek()).EventID;

                        // process any new event in queue
                        WaitHandler.TaskId = eventID;
                        Console.WriteLine("Server Generating event {0} @ {1}", eventID, DateTime.Now.ToString("hh:mm:ss"));
                        this.DoWork(eventID);
                    }
                        
                }
            }
        }

        public void DoWork(int TaskId)
        {
            Thread.Sleep(2000);
            Console.WriteLine("Publishing event with task ID {0}", TaskId);
            PublishEvent();
        }

        private void PublishEvent()
        {
            WaitHandler.GetManualEventHandler().Set();
        }
    }

    public class Client
    {
        public Client(int ClientId) 
        {
            this.ClientId = ClientId;
            this.TaskId = -1;
            new Task((o) => SubscribeToAsyncEvents(), 
                new System.Threading.CancellationToken()).Start();            
        }

        public int ClientId { get; set; }
        private int TaskId { get; set; }

        private void SubscribeToAsyncEvents()
        {
            while (true)
            {
                if (WaitHandler.GetManualEventHandler().WaitOne())
                {
                    if (WaitHandler.TaskId != TaskId)
                    {                        
                        TaskId = WaitHandler.TaskId;

                        object taskObject = new object();

                        lock (WaitHandler.TaskList)
                        {
                            WaitHandler.TaskList.Add(taskObject);
                        }

                        Console.WriteLine("Event Received by client {0} for Task Id - {1} @ {2}",
                            ClientId, TaskId, DateTime.Now.ToString("hh:mm:ss"));

                        ProcessEvent();

                        Console.WriteLine("Event Processed by client {0} for Task Id - {1} @ {2}",
                            ClientId, TaskId, DateTime.Now.ToString("hh:mm:ss"));

                        lock (WaitHandler.TaskList)
                        {
                            WaitHandler.TaskList.Remove(taskObject);
                        }

                        if (WaitHandler.TaskList.Count == 0)
                        {
                            // condition that all threads have executed
                            WaitHandler.GetManualEventHandler().Reset();
                            Console.WriteLine("All events have been processed @ {0}", DateTime.Now.ToString("hh:mm:ss"));
                        }
                    }
                }

            }

        }

        void ProcessEvent()
        {
            System.Threading.Thread.Sleep(2000);
        }
    }

    public static class WaitHandler
    {
        private static System.Threading.ManualResetEvent manual = new System.Threading.ManualResetEvent(false);
        private static System.Threading.AutoResetEvent auto = new System.Threading.AutoResetEvent(false);

        public static System.Threading.AutoResetEvent GetAutoEventHandler()
        {
            return auto;
        }

        public static System.Threading.ManualResetEvent GetManualEventHandler()
        {
            return manual;            
        }             

        public static int TaskId { get; set; }

        public static List<object> TaskList { get; set; }
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
Australia Australia
I am a Senior Software Developer / Technical Consultant in a leading software company.

Comments and Discussions