How C# asynchronous programming is different than what you think

yaser

Yaser Al-Najjar

Posted on March 18, 2019

How C# asynchronous programming is different than what you think

Why even asynchronous programming?

Non-blocking code... period!

That's the whole goal of async code, you wanna write an app that doesn't hang on the user's face so that he won't feel things are stuck!

Sample for blocking ui:

blocking
src:https://www.mithunvp.com/building-responsive-ui-using-async-await-csharp/

The same app when it's doing its job the async way

non-blocking
src:https://www.mithunvp.com/building-responsive-ui-using-async-await-csharp/

This goes on any platform and any device, whether phone, web, or even TV apps.

So what did C# bring exactly?

The problem with async programming is that it's been always hard as you know, in C/C++ it's really hard to get it done right (and testing is even harder).

On the other hand C# brought a simple way (when Anders Hejlsberg introduced async keyword) to do that that in a much less error-prone way.

Sample code for summing numbers asynchronously:

// Code sample from: https://www.dotnetperls.com/async
using System;
using System.Threading.Tasks;

class Program
{
    static void Main()
    {
        // Call async method 10 times.
        for (int i = 0; i < 10; i++)
        {
            Run2Methods(i);
        }
        // The calls are all asynchronous, so they can end at any time.
        Console.ReadLine();
    }

    static async void Run2Methods(int count)
    {
        // Run a Task that calls a method, then calls another method with ContinueWith.
        int result = await Task.Run(() => GetSum(count))
            .ContinueWith(task => MultiplyNegative1(task));
        Console.WriteLine("Run2Methods result: " + result);
    }

    static int GetSum(int count)
    {
        // This method is called first, and returns an int.
        int sum = 0;
        for (int z = 0; z < count; z++)
        {
            sum += (int)Math.Pow(z, 2);
        }
        return sum;
    }

    static int MultiplyNegative1(Task<int> task)
    {
        // This method is called second, and returns a negative int.
        return task.Result * -1;
    }
}
Enter fullscreen mode Exit fullscreen mode

You see how simple they made it, just add async await everywhere and it's gonna be magically asynchronous.

Nothing comes perfect at first

Of course, C# dudes didn't have this simple idea of async programming upfront; it's been actually developed tons of times, you can see the legacy patterns here:

https://docs.microsoft.com/en-us/dotnet/standard/async

The way other programming langs are doing it

I believe that most langs implementations are poor in doing async programming.

I mentioned the phrase "langs implementations" cuz most languages actually support async programming, but it gets tricky when implemented.

Java, Python, and even Javascript are supporting simple syntax as a "language".

Example in python

async def get_json(client, url):  
    async with client.get(url) as response:
        assert response.status == 200
        return await response.read()
Enter fullscreen mode Exit fullscreen mode

The async and await keywords have been added after C# as mentioned in PEP492

The Java way

When I was doing Android programming, threading was the normal way to do it:

// src: https://android.jlelse.eu/8-ways-to-do-asynchronous-processing-in-android-and-counting-f634dc6fae4e
new Thread(new Runnable(){
  public void run() {
    // do something here
  }
}).start();
Enter fullscreen mode Exit fullscreen mode

But now there is CompletableFuture and AsyncTask, and Kotlin emphasize on coroutines (correct me if I'm wrong).

Other langs

Go actually follows a similar model to coroutine, but in its own Goroutines.

Javascript has the exact same syntax as C#.

As for C++, wiki mentions:

In C++, await (named co_await in C++) has been officially merged into C++20 draft

The crux of the matter

This is the reason I'm writing this post, the original question goes here:

why do you think its async support is better in C# than other programming languages?

I'm gonna tell you how it's better in one word: the adoption.

Yes, you heard that right...

Whether it's a simple HTTPClient:

// src: https://stackoverflow.com/a/31102831/4565520
public Task<string> TestDownloadTask()
{
    using (HttpClient client = new HttpClient())
    {
        client.BaseAddress = new Uri(@"https://api.nasa.gov/planetary/apod");
        client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

        // You don't need await here
        return client.GetStringAsync("?concept_tags=True&api_key=DEMO_KEY");
    }
}
Enter fullscreen mode Exit fullscreen mode

A Controller in your webapp:

[HttpGet("{id}")]
public async Task<IActionResult> GetDepartment(int id){
    var department = await departmentRepository.GetByIdAsync(id);
    return Ok(department);
}
Enter fullscreen mode Exit fullscreen mode

Or even an ORM that talks to a database (EntityFramework with linq-to-sql):

return await db.students.Where(s=>s.Name.StartsWith("A")).ToListAsync();
Enter fullscreen mode Exit fullscreen mode

I've heard once famous C# author, Scott Allen, saying:

I hope we will see a day where we won't write async/await, cuz everything are just asynchronous... but it's just a hope!

Merely, cuz C# adopts async await in almost every class especially with .NET Core.

So, you will end up with mostly high performant app on every platform... if done right 😉

Know your tools well

Guess what, the async/await pattern is NOT a solution for all your asynchronous problems.

And, it's not black and white, you should understand how async/await works and also understand the costs of it.

You can achieve non-blockingness in various ways, and an event driven architecture (with a message queue fire and forget style) might help you more than relying on just adding async/await all over your code.

What do you think

Is C# doing it right? or are there much better alternatives to get a non-blocking code?

💖 💪 🙅 🚩
yaser
Yaser Al-Najjar

Posted on March 18, 2019

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related