Callback in C#

Introduction

A callback is a function that will be called when a process is done executing a specific task. i.e. if a process is going on and in between it targets if some specific task complete then it returns to the main method.

In computer programming, a callback is an executable code that is passed as an argument to other code.

Wiki

Simple example of callback methods

using System;

public class Program
{
    static void Main()
    {
        var c2 = new CallBackExample();
        c2.Method(CallBackMethod);
    }

    static void CallBackMethod(string str)
    {
        Console.WriteLine($"Callback was: {str}");
    }
}

public class CallBackExample
{

    public void Method(Action<string> callback)
    {
        callback("The message to send back");
    }
}

Let’s understand with real-time example
Suppose we have a function to handle downloads. Now, we can’t just call the function, and have it return when the download completes, because that download could take minutes or hours, and we can’t block the UI for that amount of time.

So, we make our download code to run asynchronously, which means it will return immediately before the download is completed and what we do is pass our download function a callback to call when the download is complete (we might also have one to report progress).

So, download runs in the background, calling a progress callback (so we can update a progress bar or something) and then calls another callback to say when the download is complete. It’s kind of a way of “returning” information to a calling function after the function has returned, or before it returns.

callbacks are generally categories into two categories.

  • asynchronous callbacks
  • synchronous callbacks

asynchronous callbacks

asynchronous callbacks are functions that are specified as arguments when calling a function which will start executing code in the background. When the background code finishes running, it calls the callback function to let know the work is done or to let know that something of interest has happened. Above mentioned download example is an example of asynchronous callbacks

asynchronous callbacks especially use to access or fetch some kind of resource from the web, such as downloading files from the web, accessing a database and returning data from it, etc.

For example, in the below source code file download will be completed after 5 seconds, till that time mail thread will get the end.

using System;
using System.Threading;

namespace MyDelegateExample
{
    public delegate string DownloadDelegate(string s);

    class Program
    {
        static void Main()
        {
            var downloadFile = new DownloadFile();
            var downloadDelegate = new DownloadDelegate(downloadFile.Download);
            Console.WriteLine("Main Method");
            downloadDelegate.BeginInvoke("File 1", new AsyncCallback(downloadFile.DownloadComplete), downloadDelegate);
            Console.WriteLine("Back on Main.");
            Console.WriteLine("Main Thread End!");
            Console.ReadKey();
        }
    }

    public class DownloadFile
    {
        public string Download(string str)
        {
            Thread.Sleep(5000);
            return "Downloading " + str;
        }

        public void DownloadComplete(IAsyncResult iAsyncResult)
        {
            var del = (DownloadDelegate)iAsyncResult.AsyncState;

            var result = del.EndInvoke(iAsyncResult);
            Console.WriteLine($"{result} Completed");
        }
    }
}

synchronous callbacks

synchronous means it makes a call and waits for a response. Typically, synchronous callbacks are used when we have some generic logic but to execute that generic logic, it needs some action, so we supply that action as call back method.

For example, we have a generic sort method that sorts any kind of data, but it has no idea how to compare two types of objects to sort the data. So, we pass a callback function that knows how to compare the type of objects

callback with interface

in the above example’s we have implemented callback with a delegate, lets implement callback with interface. The following code example will elaborate on the Callback mechanism with the help of Interface:


using System;

namespace CallBackInterfaceDemo
{

    interface IGst
    {
        double Cgst();
        double Sgst();
    }

    public class Maharashtra : IGst
    {
        public double Cgst()
        {
            return 9;
        }

        public double Sgst()
        {
            return  9; 
        }
    }

    public class Delhi : IGst
    {
        public double Cgst()
        {
            return 8;
        }

        public double Sgst()
        {
            return 7.5;
        }
    }

    public class Program
    {
        static void Main()
        {
            IGst maharashtra = new Maharashtra();
            CalculateTotal(587, maharashtra);

            Console.ReadLine();
        }

        static void CalculateTotal(double price, IGst gst)
        {
            var  _cgst = gst.Cgst();
            var _sgst = gst.Sgst();

            var total = price / _cgst;
            total += price / _sgst;

            Console.WriteLine(total + price);

        }
    }
}


public class CallBackExample
{

    public void Method(Action<string> callback)
    {
        callback("The message to send back");
    }
}

synchronous and asynchronous delegates

Below sample code to demonstrate synchronous and asynchronous delegates, in below code will call the same method multiple times so in synchronous call required time will calculate as no of calls X time delay. asynchronous call required time will depend on different factors but surely it will be less the synchronous required time.

using System;
using System.Threading;

namespace Operation
{
    class Program
    {
        public delegate string TextDelegate(string txt);

        static void Main()
        {
            Console.WriteLine("Main thread started!");
            SynchronousSample();
            AsynchronousSample();

            Console.WriteLine("Main thread exits!");
            Console.ReadKey();
        }

        static void SynchronousSample()
        {
            var dm = new TextDelegate(DelegateMethod);
            Console.WriteLine(dm("Delegate 1"));
            Console.WriteLine(dm("Delegate 2"));
            Console.WriteLine(dm("Delegate 3"));
            Console.WriteLine(dm("Delegate 4"));
            Console.WriteLine(dm("Delegate 5"));
            Console.WriteLine("Synchronous call is completed!");
        }

        static void AsynchronousSample()
        {

            var dm = new TextDelegate(DelegateMethod);

            var result1 = dm.BeginInvoke("Delegate 1", null, null);
            var result2 = dm.BeginInvoke("Delegate 2", null, null);
            var result3 = dm.BeginInvoke("Delegate 3", null, null);
            var result4 = dm.BeginInvoke("Delegate 4", null, null);
            var result5 = dm.BeginInvoke("Delegate 5", null, null);

            var r1 = dm.EndInvoke(result1);
            Console.WriteLine(r1);
            var r2 = dm.EndInvoke(result2);
            Console.WriteLine(r2);
            var r3 = dm.EndInvoke(result3);
            Console.WriteLine(r3);
            var r4 = dm.EndInvoke(result4);
            Console.WriteLine(r4);
            var r5 = dm.EndInvoke(result5);
            Console.WriteLine(r5);

            Console.WriteLine("Asynchronous call is completed!");
        }


        static string DelegateMethod(string str)
        {
            Thread.Sleep(2500);
            Console.WriteLine($"{str} Thread id is: {Thread.CurrentThread.ManagedThreadId.ToString()}");
            return str + " completed";
        }
    }
}

Online free quiz for delegates and multicast delegate, you can also read more about delegate and multicast delegate.

Leave a Reply

Your email address will not be published. Required fields are marked *