Saturday, November 14, 2015

Non Blocking Programming (Async, Await & Task)

⚙️ What is async / await in .NET?

In simple terms:

async and await enable asynchronous, non-blocking programming in .NET.

They allow your app to perform long-running tasks (like database calls, file I/O, or API calls) without freezing the main thread.



๐Ÿงฉ Why Do We Need It?

Imagine a web API endpoint that calls a database and waits for the response.
If this were synchronous, that thread would just sit idle waiting — wasting server resources.

But with async/await, the thread is released back to the thread pool while waiting.
That means:

  • Better scalability — more requests can be handled.

  • No UI freeze (in desktop apps).

  • Efficient use of system threads.


๐Ÿง  Key Concepts

ConceptDescription
async keywordMarks a method as asynchronous — allows use of await inside it.
await keywordSuspends the method until the awaited task completes, without blocking the thread.
TaskRepresents an ongoing operation (future result).
Task<T>Represents an async operation that returns a result.
void async methodsOnly used for event handlers — otherwise avoid.

๐Ÿ’ก Example

๐Ÿ”น Synchronous method (blocking)

public string GetData() { var data = File.ReadAllText("data.txt"); // blocks until done return data; }

๐Ÿ”น Asynchronous method (non-blocking)

public async Task<string> GetDataAsync() { var data = await File.ReadAllTextAsync("data.txt"); // non-blocking return data; }

✅ While waiting for File.ReadAllTextAsync() to finish,
the current thread is released to handle other work.


๐Ÿงฉ Example in ASP.NET Core Controller

[HttpGet("user/{id}")] public async Task<IActionResult> GetUser(int id) { var user = await _userRepository.GetUserByIdAsync(id); return Ok(user); }

Here:

  • The thread executing this request can return to the thread pool while waiting on the DB.

  • Once the task completes, .NET resumes the method and sends the response.

This allows ASP.NET Core to handle many concurrent requests efficiently.


๐Ÿ”„ Async Flow Diagram

Request → Controller → await Repository call → Thread released ↓ DB operation completes ↓ Continuation resumes → Response sent

๐Ÿง  Behind the Scenes

When the compiler sees async and await, it:

  • Transforms the method into a state machine.

  • Handles continuations automatically (what happens after the task completes).

  • Avoids the need for callbacks or manual threading.


⚙️ Best Practices

✅ Use async all the way down (from controller → repository → I/O).
✅ Return Task or Task<T> (not void).
✅ Use ConfigureAwait(false) in library code (not needed in ASP.NET Core usually).
✅ Avoid blocking calls like .Result or .Wait() — they can cause deadlocks.
✅ Combine async calls efficiently using Task.WhenAll().


๐Ÿงพ Summary Table

AspectSynchronousAsynchronous
ThreadBlocked until work completesFreed while waiting
PerformanceScales poorly under loadScales efficiently
KeywordNoneasync / await
Return typeTTask<T>
Use caseQuick operationsI/O-bound operations

⚙️ Real-world Example in AWS/.NET

If your ASP.NET Core Web API calls:

  • AWS DynamoDB

  • S3 file upload

  • SNS message publish

All those SDKs have async methods (e.g., PutItemAsync, UploadAsync, PublishAsync).
Using await makes them non-blocking, improving throughput.

-----------------------------------------------------------------------------------------------------------------------------

๐Ÿงฉ Difference between Task and Task<T>

FeatureTaskTask<T>
Return TypeRepresents an asynchronous operation that does not return a value.Represents an asynchronous operation that returns a result of type T.
Equivalent to (sync)Like void in synchronous methods.Like returning a value of type T in synchronous methods.
UsageWhen the method performs work but doesn’t need to return a value.When the method performs work and returns a value asynchronously.
Example Method Signaturepublic async Task DoWorkAsync()public async Task<int> GetCountAsync()
How to Awaitawait DoWorkAsync();int count = await GetCountAsync();
When to UseFire-and-forget tasks (but still awaitable) like logging, sending email, etc.Database calls, HTTP requests, file reads, calculations, etc.
Completion HandlingOnly completion (success/failure)Completion plus a result value

๐Ÿ”น Example 1 — Task (no return value)

public async Task SendEmailAsync(string to) { await emailService.SendAsync(to, "Welcome!", "Thanks for joining us!"); }

Usage:

await SendEmailAsync("user@example.com");

✅ You’re waiting for completion — but there’s no result to retrieve.


๐Ÿ”น Example 2 — Task<T> (returns a value)

public async Task<int> GetUserCountAsync() { return await _dbContext.Users.CountAsync(); }

Usage:

int count = await GetUserCountAsync();

✅ You’re waiting for the task to complete and getting back a result (int).

Friday, November 13, 2015

Mark a method Deprecated (Obsolete)

Using Obsolete attribute a method can be marked as Deprecated.

Three overloaded methods for Obsolete 
1. Mark a method Deprecated
2. Mark a method Deprecated with showing message (suggest new method to use)


2. Mark a method Deprecated with making it error on compilation


Thursday, November 12, 2015

var Keyword

Defining a variable as var enables to assign any data type value. var is implicit data type declaration.
var str = "hello";

var num = 10;

var is statically defined: Compiler checks assigned value to var and create data type accordingly at the declaration (compile time)
var num = 10; //compiler creates num as int at this declaration
var str = "hello"//compiler creates str as string at this declaration

var is strongly typed: At declaration compiler create appropriate data type by checking assigned value so from next statement of declaration variable behaves like strongly typed variable
str++ //error because its now string
num++ //allowed because its now int
intellisense showing all prop/methods of string for 'str'


object dynamic can also be used but these both resolved at run time. They are dynamically defined and not strongly typed.

Dynamic Keyword

dynamic is a type introduced in C# 2010, making a variable as dynamic type, skip compile time checking for that variable, it allows any operation / call to write at compile time.
If written code not get validated at run-time then at run time it throw error.
dynamic keyword is an example of Late Binding
Early Binding : Compile time checking


Late Binding : Run time checking not compile time

dynamic converts early binding to late binding

Source Code: 
Below code compiled successfully
    class Program
    {
        static void Main(string[] args)
        {
            //Example1 allowing mathematical operation on string at compile time
            dynamic str = "hello";
            str++;

            //Example2 allowing Update() method call that does not exist, at compile time
            dynamic objStudent = new student();
            objStudent.Update();
        }
    }
    class student
    {
        public int RollNo { get; set; }
        public string Name { get; set; }
        public void Add()
        {
        }
    }


Errors at run-time
Error 1

Error 2


Indexer

An Indexer is a public property of a class that is used to fetch values from a collection contained by class in an efficient & easy way.
Indexer makes a class as a virtual array.
  1. this keyword is used to create indexer
  2. Indexer can be overloaded
  3. More then one parameters can be used for indexing

Source Code:
public class Student
{
    public int RollNo { get; set; }
    public string Name { get; set; }
    public string Class { get; set; }
}
class Program
{
    static void Main(string[] args)
    {
        school objSchool = new school();
        
        //Class object used as an array using Indexer
        Student obj1 = objSchool[2];    //Indexer1  
        Student obj2 = objSchool["Ravi"]; //Indexer2
        
        Console.WriteLine("Student Roll No:{0}, Name:{1}",obj1.RollNo, obj1.Name);
        Console.WriteLine("Student Roll No:{0}, Name:{1}", obj2.RollNo, obj2.Name);
        Console.ReadLine();
    }

    class school
    {
        private List<Student> lstStudent = new List<Student>();
        public school()
        {
            lstStudent.Add(new Student { RollNo = 1, Name = "Ram", Class = "5th" });
            lstStudent.Add(new Student { RollNo = 2, Name = "Shiv", Class = "6th" });
            lstStudent.Add(new Student { RollNo = 3, Name = "Ravi", Class = "5th" });
        }
      
        public Student this[int rollNo]  //Indexer
        {
            get
            {
                return lstStudent.Find(new Predicate<Student>(x => x.RollNo == rollNo));
            }
            set
            {
              //lstStudent.Find(new Predicate<Student>(x => x.RollNo == rollNo)).RollNo = rollNo; //Set can be used but here it does not have meaning
            }
        }
        public Student this[string name] //overloading of indexer
        {
            get
            {
                return lstStudent.Find(new Predicate<Student>(x => x.Name == name));
            }
            set
            {
             //lstStudent.Find(new Predicate<Student>(x => x.Name == name)).Name = name;
            }
        }
    }
}

Tuesday, November 10, 2015

IComparable & IComparer Interfaces

IComparable & IComparer Interfaces are used to provide comparison mechanism to collection of objects that comparison scheme is used by the collection for sorting functions.

IComparable: It defines a way of comparison for two similar class objects. A collection of objects internally uses this defined way to sort objects.
Using IComparable we can define only one way of comparison for a collection of objects.
This is internal comparer
We defines CompareTo method of IComparable  that returns int
            public int CompareTo(object obj)
            {
                return this.Age.CompareTo(((Person)obj).Age);
            }

IComparer: It defines multiple ways of comparison for two similar class objects.
Using IComparer we can define multiple ways of comparison for a collection of objects.
This comparison take place externally
We defines Compare method of IComparer that returns int
            public int Compare(Student x, Student y)
            {
                return string.Compare(x.Name, y.Name);
            }


Source Code:
        #region IComparable
        public class Person : IComparable
        {
            public string Name { get; set; }
            public int Age { get; set; }

            public int CompareTo(object obj)
            {
                return this.Age.CompareTo(((Person)obj).Age);
            }
        }

        //Generic Icomparable example
        public class Employee : IComparable<Employee>
        {
            public string Name { get; set; }
            public int Salary { get; set; }
           
            public int CompareTo(Employee other)
            {
                return this.Salary.CompareTo(other.Salary);
            }
        }
        #endregion

        #region IComparer
        public class Student
        {
            public string Name { get; set; }
            public double Percentile { get; set; }
        }

        public class SortByName : IComparer<Student>
        {
            public int Compare(Student x, Student y)
            {
                return string.Compare(x.Name, y.Name);
            }
        }
        public class SortByPercentile : IComparer<Student>
        {
            public int Compare(Student x, Student y)
            {
                if (x.Percentile == y.Percentile)
                    return 0;
                else if (x.Percentile > y.Percentile)
                    return 1;
                else
                    return -1;
            }
        }

        #endregion

Client Code:
        static void Main(string[] args)
        {
            #region IComparable
            Person me = new Person { Name = "Anand", Age = 32 };
            Person MyFather = new Person { Name = "PSTomar", Age = 65 };
            Person MyGrandFather = new Person { Name = "DSTomar", Age = 85 };

            List<Person> lstPerson = new List<Person>();

            lstPerson.Add(MyFather);
            lstPerson.Add(me);
            lstPerson.Add(MyGrandFather);

            lstPerson.Sort();
            Console.WriteLine("Result of IComparable example :");
            foreach (Person p in lstPerson)
                Console.WriteLine("Name : {0}, Age : {1} ", p.Name, p.Age);
            Console.ReadLine();
            #endregion

            #region IComparer
            Student Megha = new Student { Name = "Megha", Percentile = 32.55 };
            Student Renuka = new Student { Name = "Renuka", Percentile = 65.12 };
            Student Ghanshyam = new Student { Name = "Ghanshyam", Percentile = 80.11 };

            List<Student> lstStudent = new List<Student>();

            lstStudent.Add(Megha);
            lstStudent.Add(Renuka);
            lstStudent.Add(Ghanshyam);

            lstStudent.Sort(new SortByName());
            Console.WriteLine("Result of IComparer example :");
            foreach (Student p in lstStudent)
                Console.WriteLine("Name : {0}, Percentile : {1} ", p.Name, p.Percentile);
            Console.ReadLine();
           
            lstStudent.Sort(new SortByPercentile());
            foreach (Student p in lstStudent)
                Console.WriteLine("Name : {0}, Percentile : {1} ", p.Name, p.Percentile);
            Console.ReadLine();
            #endregion
        }

CI/CD - Safe DB Changes/Migrations

Safe DB Migrations means updating your database schema without breaking the running application and without downtime . In real systems (A...