C# Pub-Sub example how to make function called in the subscriber async when notification published by publisher

Viewed 12

Hope I phrased the question correctly, feel free to give suggestions in order to make it more clear.

I basically just need to make this function async:

protected virtual void OnNotificationReceived(Publisher p, NotificationEvent e)

Not sure how to modify the rest of the code to make it work, please help.

Publisher class

 class Publisher{
    
        //publishers name
        public string PublisherName { get; private set; }
    
        //publishers notification interval
        public int NotificationInterval { get; private set; }
    
        // declare a delegate function
        public delegate void Notify(Publisher p, NotificationEvent e);
    
        // declare an event variable of the delegate function
        public event Notify OnPublish;
    
        // class constructor
        public Publisher(string _publisherName, int _notificationInterval){
            PublisherName = _publisherName;
            NotificationInterval = _notificationInterval;
        }
    
        //publish function publishes a Notification Event
        public void Publish(){
    
            while (true){
    
                // fire event after certain interval
                Thread.Sleep(NotificationInterval);
    
                if (OnPublish != null)
                {
                    NotificationEvent notificationObj = new NotificationEvent(DateTime.Now, "New Notification Arrived from");
                    OnPublish(this, notificationObj);
                }
                Thread.Yield();
            }
        }
    }

Subscriber class

 class Subscriber{
    
        public string SubscriberName { get; private set; }
    
        public Subscriber(string _subscriberName){
            SubscriberName = _subscriberName;
        }
    
        // This function subscribe to the events of the publisher
        public void Subscribe(Publisher p){
    
            // register OnNotificationReceived with publisher event
            p.OnPublish += OnNotificationReceived;  // multicast delegate 
    
        }
    
        // This function unsubscribe from the events of the publisher
        public void Unsubscribe(Publisher p){
    
            // unregister OnNotificationReceived from publisher
            p.OnPublish -= OnNotificationReceived;  // multicast delegate 
        }
    
        // It get executed when the event published by the Publisher
        // ***I want to make this method async here:***
        protected virtual void OnNotificationReceived(Publisher p, NotificationEvent e){
    
            Console.WriteLine("Hey " + SubscriberName + ", " + e.NotificationMessage +" - "+ p.PublisherName + " at " + e.NotificationDate);
        }
    }
1 Answers

Just add the async keyword. You can do this even though the method returns void instead of Task.

protected virtual /**/ async /**/ void OnNotificationReceived(Publisher p, NotificationEvent e){
    await Task.Delay(TimeSpan.FromSeconds(1)); // See? It's async
    Console.WriteLine("Hey " + SubscriberName + ", " + e.NotificationMessage +" - "+ p.PublisherName + " at " + e.NotificationDate);
}

See it compile

Just be aware that in my code above, the call to Console.WriteLine will happen asynchronously (approximately one second later) instead of synchronously as before. This can lead to race conditions if you're not prepared for it.

Also be aware that whoever calls this async void method will have no way of knowing when it completes. If callers need to know when it completes then make the method return a Task; then callers can await it.

Also be aware that any exceptions thrown in an async void method will most likely be lost. That's not necessarily the case (example, example... assuming you subscribe to those events). So it might be wise to wrap all the code in your async void method in a try/catch and respond intelligently to any thrown exceptions.

Here are other thoughts on returning Task vs void: async/await - when to return a Task vs void?

Related