Skip to the content.

Tutorial 3: Understanding Async/Await (In Plain English)

🎯 What You’ll Learn

📚 Prerequisites

🍳 The Restaurant Analogy

Imagine you’re at a restaurant. There are two ways to get your food:

Method 1: Stand and Wait (Synchronous)

1. You order a burger
2. You stand at the counter
3. You can't do anything else
4. You just wait... and wait...
5. Finally get your burger
6. Now you can do the next thing

Method 2: Take a Number (Asynchronous)

1. You order a burger
2. They give you a number
3. You sit down and chat with friends
4. You check your phone
5. They call your number
6. You get your burger

Async/Await is Method 2! Your program doesn’t freeze while waiting.

💻 In Code Terms

Without Async (Program Freezes)

// DON'T DO THIS - Your program will freeze!
public static void Main()
{
    Console.WriteLine("Starting download...");

    // This BLOCKS - program frozen here!
    var result = DownloadWebpage("https://slow-website.com");  // Wait..... wait..... wait.....

    Console.WriteLine("Finally done!");  // Only runs after download finishes
}

With Async (Program Stays Responsive)

public static async Task Main()  // Note: async Task
{
    Console.WriteLine("Starting download...");

    // This DOESN'T BLOCK - program can do other things
    var result = await DownloadWebpageAsync("https://slow-website.com");

    Console.WriteLine("Done!");  // Runs after download, but program wasn't frozen
}

🔑 The Golden Rules

Rule 1: Async Methods End with “Async”

// Regular methods (avoid these for web requests)
Curl.Execute()
File.ReadAllText()
Download()

// Async methods (use these!)
Curl.ExecuteAsync()
File.ReadAllTextAsync()
DownloadAsync()

Rule 2: Always Use ‘await’ with Async Methods

// WRONG - Missing await
var result = Curl.ExecuteAsync("curl https://api.com");

// RIGHT - With await
var result = await Curl.ExecuteAsync("curl https://api.com");

Rule 3: Methods Using ‘await’ Must Be ‘async’

// WRONG - Method not marked as async
static Task<string> GetData()
{
    var result = await Curl.ExecuteAsync("curl https://api.com");  // ERROR!
    return result.Body;
}

// RIGHT - Method marked as async
static async Task<string> GetData()
{
    var result = await Curl.ExecuteAsync("curl https://api.com");  // Works!
    return result.Body;
}

🎯 Real Examples with CurlDotNet

Example 1: Simple Async Call

using System;
using System.Threading.Tasks;
using CurlDotNet;

class Program
{
    static async Task Main()  // async Task for Main
    {
        Console.WriteLine("Fetching data...");

        // await tells C# to wait here (but not freeze)
        var result = await Curl.ExecuteAsync("curl https://api.github.com");

        Console.WriteLine($"Got {result.Body.Length} characters");
    }
}

Example 2: Multiple Async Calls (One at a Time)

static async Task Main()
{
    // These happen one after another
    var result1 = await Curl.ExecuteAsync("curl https://api.github.com");
    Console.WriteLine("Got first response");

    var result2 = await Curl.ExecuteAsync("curl https://api.bitbucket.org");
    Console.WriteLine("Got second response");

    var result3 = await Curl.ExecuteAsync("curl https://api.gitlab.com");
    Console.WriteLine("Got third response");
}

Example 3: Multiple Async Calls (All at Once!)

static async Task Main()
{
    // Start all three at the same time!
    var task1 = Curl.ExecuteAsync("curl https://api.github.com");
    var task2 = Curl.ExecuteAsync("curl https://api.bitbucket.org");
    var task3 = Curl.ExecuteAsync("curl https://api.gitlab.com");

    // Wait for all to complete
    var results = await Task.WhenAll(task1, task2, task3);

    Console.WriteLine("Got all three responses at once!");
}

🤔 What’s Really Happening?

When you use await:

  1. Request Starts - The HTTP request begins
  2. Control Returns - Your program can do other things
  3. Request Completes - The server responds
  4. Code Resumes - Your code continues from the await line

It’s like ordering pizza:

  1. You call and order (start request)
  2. You watch TV while waiting (program does other things)
  3. Doorbell rings (request completes)
  4. You eat pizza (code continues)

⚡ Async vs Sync Comparison

Synchronous (Blocking)

// THIS FREEZES YOUR PROGRAM
public void DownloadFiles()
{
    var file1 = DownloadFile("file1.zip");  // Wait 5 seconds...
    var file2 = DownloadFile("file2.zip");  // Wait 5 seconds...
    var file3 = DownloadFile("file3.zip");  // Wait 5 seconds...
    // Total time: 15 seconds, program frozen the whole time
}

Asynchronous (Non-Blocking)

// THIS DOESN'T FREEZE
public async Task DownloadFilesAsync()
{
    var task1 = DownloadFileAsync("file1.zip");
    var task2 = DownloadFileAsync("file2.zip");
    var task3 = DownloadFileAsync("file3.zip");

    await Task.WhenAll(task1, task2, task3);
    // Total time: 5 seconds, all download at once!
}

❌ Common Mistakes

Mistake 1: Forgetting await

// WRONG - This doesn't wait for the result!
static async Task Main()
{
    var resultTask = Curl.ExecuteAsync("curl https://api.com");
    Console.WriteLine(resultTask.Body);  // ERROR! resultTask is a Task, not a result
}

// RIGHT - Use await to get the actual result
static async Task Main()
{
    var result = await Curl.ExecuteAsync("curl https://api.com");
    Console.WriteLine(result.Body);  // Works! result is the actual response
}

Mistake 2: Using .Result or .Wait()

// WRONG - Can cause deadlocks!
static void Main()
{
    var result = Curl.ExecuteAsync("curl https://api.com").Result;  // BAD!
    // or
    var task = Curl.ExecuteAsync("curl https://api.com");
    task.Wait();  // ALSO BAD!
}

// RIGHT - Use async/await all the way
static async Task Main()
{
    var result = await Curl.ExecuteAsync("curl https://api.com");  // GOOD!
}

Mistake 3: Not Making Method Async

// WRONG - Method not async
static Task<string> GetData()
{
    var result = await Curl.ExecuteAsync("curl https://api.com");  // ERROR!
    return result.Body;
}

// RIGHT - Method is async
static async Task<string> GetData()
{
    var result = await Curl.ExecuteAsync("curl https://api.com");  // Works!
    return result.Body;
}

🎮 Interactive Example

Try this code and see the difference:

using System;
using System.Threading.Tasks;
using System.Diagnostics;
using CurlDotNet;

class Program
{
    static async Task Main()
    {
        // Method 1: One at a time (slow)
        var stopwatch = Stopwatch.StartNew();

        var result1 = await Curl.ExecuteAsync("curl https://httpbin.org/delay/1");
        var result2 = await Curl.ExecuteAsync("curl https://httpbin.org/delay/1");
        var result3 = await Curl.ExecuteAsync("curl https://httpbin.org/delay/1");

        Console.WriteLine($"Sequential: {stopwatch.ElapsedMilliseconds}ms (about 3 seconds)");

        // Method 2: All at once (fast!)
        stopwatch.Restart();

        var task1 = Curl.ExecuteAsync("curl https://httpbin.org/delay/1");
        var task2 = Curl.ExecuteAsync("curl https://httpbin.org/delay/1");
        var task3 = Curl.ExecuteAsync("curl https://httpbin.org/delay/1");

        await Task.WhenAll(task1, task2, task3);

        Console.WriteLine($"Parallel: {stopwatch.ElapsedMilliseconds}ms (about 1 second)");
    }
}

📊 Quick Reference

Keyword What It Does When to Use
async Marks a method as asynchronous When method contains await
await Waits for async operation Before any ...Async() method
Task Represents an ongoing operation Return type for async methods
Task<T> Ongoing operation with result When async method returns value

🎯 Simple Rules to Remember

  1. See Async in method name? → Use await
  2. Using await in method? → Mark method as async
  3. Method is async? → Return Task or Task<T>
  4. Multiple operations? → Consider Task.WhenAll()

🚀 Next Steps

Now that you understand async/await:

  1. Next TutorialYour First Request
  2. Practice → Try the interactive example above
  3. Experiment → What happens without await?

🤔 FAQs

Q: Why not just use synchronous methods? A: Your application would freeze during network requests. Users hate frozen apps!

Q: Can I use async without await? A: Technically yes, but you usually shouldn’t. You’d lose the benefit.

Q: Is async/await faster? A: For single operations, no. For multiple operations or keeping UI responsive, yes!

Q: Do I always need async/await? A: For network requests, file I/O, and database calls - yes! For simple calculations - no.

📚 Summary


Ready to make your first request?Your First Request

Still confused? That’s normal! Try the examples and it will click. Check Common Issues if you get stuck.