Skip to main content

Async/Await Operations

Level: Intermediate

ℹ️ What You'll Learn
  • Async definition: Operation runs in background, thread freed to handle other requests (better scalability)
  • Synchronous blocking: var student = _service.GetStudent(id); blocks thread while waiting for database
  • Asynchronous non-blocking: var student = await _service.GetStudentAsync(id); releases thread while waiting
  • async keyword: Marks method as asynchronous (allows await inside)
  • await keyword: Wait for Task to complete, but release thread to other work
  • Task<T> return type: async Task<Student> GetStudentAsync(int id) returns result after completion
  • Database operations async: await _context.Students.FirstOrDefaultAsync(s => s.Id == id) (EF Core)
  • HTTP calls async: await httpClient.GetAsync("https://api.example.com/data") (external API)
  • Task.WhenAll for parallel: await Task.WhenAll(task1, task2, task3) run multiple operations in parallel (faster)
  • School Management example: Load student + teacher + exams in parallel (instead of sequential)
  • Exception handling async: try { await operation } catch { handle error } same as synchronous
  • Common pitfall: .Result blocks thread (defeats async purpose), use await instead
  • Thread efficiency: 10,000 users on async = 1 thread, 10,000 users on sync = 10,000 threads (server crashes)
  • Every Web API action should be async: public async Task<ActionResult<Student>> GetStudent(int id)

Why Async?

Synchronous = blocks thread (slow)

Request → Database wait → Response
(thread stuck waiting)

Asynchronous = releases thread (fast)

Request → Database query in background
→ Thread handles other requests
→ Database returns → Response

Basic Async Pattern

// Synchronous (slow)
public Student GetStudent(int id)
{
return _repository.GetStudent(id); // Thread waits
}

// Asynchronous (fast)
public async Task<Student> GetStudentAsync(int id)
{
return await _repository.GetStudentAsync(id); // Thread freed
}

Controller with Async

[HttpGet("{id}")]
public async Task<ActionResult<Student>> GetStudent(int id)
{
var student = await _service.GetStudentAsync(id);
if (student == null)
return NotFound();

return Ok(student);
}

[HttpPost]
public async Task<ActionResult<Student>> CreateStudent([FromBody] Student student)
{
var result = await _service.CreateStudentAsync(student);
return CreatedAtAction(nameof(GetStudent), new { id = result.Id }, result);
}

[HttpPut("{id}")]
public async Task<ActionResult> UpdateStudent(int id, [FromBody] Student student)
{
await _service.UpdateStudentAsync(id, student);
return NoContent();
}

[HttpDelete("{id}")]
public async Task<ActionResult> DeleteStudent(int id)
{
await _service.DeleteStudentAsync(id);
return NoContent();
}

Service Layer

public class StudentService : IStudentService
{
public async Task<List<Student>> GetStudentsAsync()
{
return await _repository.GetStudentsAsync();
}

public async Task<Student> GetStudentAsync(int id)
{
return await _repository.GetStudentAsync(id);
}

public async Task CreateStudentAsync(Student student)
{
await _repository.AddAsync(student);
await _repository.SaveChangesAsync();
}
}

Multiple Async Operations

[HttpGet("{id}/details")]
public async Task<ActionResult> GetStudentDetails(int id)
{
// Parallel operations
var studentTask = _studentService.GetStudentAsync(id);
var examsTask = _examService.GetStudentExamsAsync(id);
var feesTask = _feeService.GetStudentFeesAsync(id);

await Task.WhenAll(studentTask, examsTask, feesTask);

var student = await studentTask;
var exams = await examsTask;
var fees = await feesTask;

return Ok(new { student, exams, fees });
}

Error Handling

[HttpPost]
public async Task<ActionResult<Student>> CreateStudent([FromBody] Student student)
{
try
{
var result = await _service.CreateStudentAsync(student);
return CreatedAtAction(nameof(GetStudent), new { id = result.Id }, result);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error creating student");
return StatusCode(500, new { error = "Failed to create student" });
}
}

Key Takeaways

  • Async = non-blocking
  • Await = wait for operation
  • Task = asynchronous operation
  • Improves scalability
  • Always use async in APIs
💡 Async Tip

All the way async. If controller is async, service must be async.

🤖Use AI to Learn Faster

Use ChatGPT, Claude, or Copilot to go deeper on Async Operations. Try these prompts:

  • "Why use async/await?"
  • "What's the difference between Task and Task<T>?"
  • "How do I run multiple async operations in parallel?"
  • "Quiz me on async/await"

💡 Tip: After reading this article, paste your own code into AI and ask "What could go wrong here and why?" — fastest way to find edge cases and deepen understanding.

nexcoding.in