Day 14 of 30-Day .NET Challenge: Limit Concurrent Async Operations
Tags: beginners, programming, csharp, dotnet
Published: 2024-04-02 05:54:00


## Introduction

The article highlights the importance of limiting the concurrent asynchronous operations which in turn improves performance.

### Learning Objectives

* The common mistake all developers do

* How to use limit concurrent async operations

* Best Practices

### Prerequisites for Developers

* Basic understanding of C# programming language

* Basic understanding of asynchronous programming using async await

## Getting Started

### The common mistake all developers do

Consider an example where the user wants to load data asynchronously within a method and it highlights the common mistake developers make
```csharp
    (async item => await ProcessItem(item));
```

```csharp
    /// <summary>
    /// Old approach with classic async await 
    /// </summary>
    /// <returns></returns>
    public async static Task OldApproach(List<string> items)
    {
        var tasks = items.Select(async item => await ProcessItem(item));
        await Task.WhenAll(tasks);
    }
```
The approach may look clean and simple but it initiates tasks for each item in the collection concurrently. This can cause system strain under heavy List<string> items which will produce poor application performance.

### Optimized approach with Concurrency Limit

Let’s transform the above method using SemaphoreSlim to limit the number of concurrent asynchronous operations. The following code snippet demonstrates the more refined approach.
```csharp
    /// <summary>
    /// Optimized approach with limit concurrency
    /// </summary>
    /// <returns></returns>
    public static async Task OptimizedApproachAsync(List<string> items, int maxConcurrency = 10)
    {
        using (var semaphore = new SemaphoreSlim(maxConcurrency))
        {
            var tasks = items.Select(async item =>
            {
                await semaphore.WaitAsync(); // Limit concurrency by waiting for the semaphore.
                try
                {
                    await ProcessItem(item);
                }
                finally
                {
                    semaphore.Release(); // Release the semaphore to allow other operations.
                }
            });
    
            await Task.WhenAll(tasks);
        }
    }
```
The aforementioned code prevents the system choked by too many concurrent tasks.

## Best Practices

Please find below the best practices 

### Limit Concurrency

To balance system load and resources, it is recommended to use SemaphoreSlim 

### Avoid Blocking Calls

Avoid using .Result or .Wait() as they can lead to deadlocks and degrade performance.

### Async all the way

Avoid mixing async and sync code, ensure all methods are async from top to bottom to prevent deadlock and make optimal use of resources.

## Conclusion

Asynchronous programming in C# involves more than just understanding the async and await keywords; it requires more features like concurrency, resource utilization, and code structure

## Complete Code on GitHub
[GitHub — ssukhpinder/30DayChallenge.Net](https://github.com/ssukhpinder/30DayChallenge.Net/tree/main)

### C# Programming🚀

Thank you for being a part of the C# community! Before you leave:

#### If you’ve made it this far, please show your appreciation with a clap and follow the author! 👏️️

Follow us: [X](https://twitter.com/sukhsukhpinder) | [LinkedIn](https://www.linkedin.com/in/sukhpinder-singh/) | [Dev.to](https://dev.to/ssukhpinder) | [Hashnode](https://dotnet.hashnode.dev/) | [Newsletter](https://www.linkedin.com/newsletters/net-programming-7031098498754195456/) | [Tumblr](https://www.tumblr.com/settings/blog/codewithsukh)

Visit our other platforms: [GitHub](https://github.com/ssukhpinder) | [Instagram](https://www.instagram.com/codewithsukh/) | [Tiktok](https://www.tiktok.com/@codewithsukh) | [Quora](https://www.quora.com/profile/Sukhpinder-Singh-4) | [Daily.dev](https://app.daily.dev/devcard)

More content at [C# Programming](https://medium.com/c-sharp-progarmming)