0

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);
        }
    }
Razvan Emil
  • 533
  • 9
  • 25

1 Answers1

1

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?

Matt Thomas
  • 5,279
  • 4
  • 27
  • 59
  • Thanks for the answer but I get an error here: p.OnPublish += OnNotificationReceived saying: "Task Subscriber.OnNotificationReceived(Publisher p, NotificationEvent e) has wrong return type" when i change it to async Task – Razvan Emil Sep 22 '22 at 19:17
  • 1
    @RazvanEmil In this case you will want to return `void` instead of `Task`. Events are usually fire-and-forget, meaning the caller of `OnNotificationReceived` (i.e. whoever raises the event) does not need to know when it completes. I only mentioned returning a `Task` because it'll be something to think about in the future in other scenarios. – Matt Thomas Sep 22 '22 at 19:23
  • yes good point I dont think I need to await it, within the OnNotificationReceived function in my code i am just further firing an MQTT message to an MQTT broker, the function is async, using a library,but I dont think I need to await that.... so I just added FireMQTTMessage(message).ConfigureAwait(false) not sure if there is a problem with that... – Razvan Emil Sep 22 '22 at 19:26
  • 1
    `async void` is almost always a terribad idea; I don't see anything that would make it OK here – Marc Gravell Sep 22 '22 at 20:04
  • @MarcGravell True. I added another caveat about losing exceptions and linked to another question discussing the differences. It probably would have been more productive for me to link to that from the beginning ¯\\_(ツ)_/¯ – Matt Thomas Sep 22 '22 at 20:10