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).

No comments:

Post a Comment

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...