Handling Asynchronous API Calls

Explore top LinkedIn content from expert professionals.

Summary

Handling asynchronous API calls means managing requests that run in the background without blocking the main program, allowing multiple tasks to happen at once and speeding up software response times. This technique is crucial for building applications that stay responsive and can process several operations at the same time, especially when tasks are independent.

  • Go parallel: When making multiple independent API requests, run them concurrently so your app doesn’t have to wait for each call to finish one by one.
  • Manage resources: Control how many async operations run at once to avoid overloading your system and use thread-safe collections to prevent data errors.
  • Handle timeouts: Always set time limits on your API requests and deal with exceptions properly, so one slow or failed call doesn’t impact the whole process.
Summarized by AI based on LinkedIn member posts
  • View profile for Anton Martyniuk

    Helping 90K+ .NET Engineers reach Senior and Software Architecture level | Microsoft MVP | .NET Software Architect | Founder: antondevtips

    98,954 followers

    𝟭𝟬 𝗔𝘀𝘆𝗻𝗰 𝗠𝗶𝘀𝘁𝗮𝗸𝗲𝘀 𝗞𝗶𝗹𝗹𝗶𝗻𝗴 𝗬𝗼𝘂𝗿 𝗔𝗦𝗣.𝗡𝗘𝗧 𝗖𝗼𝗿𝗲 𝗔𝗽𝗽 I've reviewed dozens of .NET Core backends that suffered mysterious slowdowns and memory spikes. Every time, the root cause was the same: bad async code. These async mistakes aren't obvious. They don't throw errors. They just slowly kill your app. Here are the 10 most common async pitfalls I see (and how to fix them): Stop making these costly errors 👇 𝟭/ 𝗡𝗼𝘁 𝘂𝘀𝗶𝗻𝗴 𝗖𝗮𝗻𝗰𝗲𝗹𝗹𝗮𝘁𝗶𝗼𝗻𝗧𝗼𝗸𝗲𝗻 ↳ Requests keep running after clients disconnect ↳ Wasted CPU cycles and memory leaks ✅ Always pass CancellationToken through your async chain 𝟮/ 𝗕𝗹𝗼𝗰𝗸𝗶𝗻𝗴 𝗼𝗻 𝗮𝘀𝘆𝗻𝗰 𝗰𝗼𝗱𝗲 ↳ Using .Result, Wait(), GetAwaiter() .GetResult() ↳ Thread pool starvation = application freezes ✅ Use await consistently, never block on async calls 𝟯/ 𝗡𝗼 𝘁𝗶𝗺𝗲𝗼𝘂𝘁𝘀 𝗼𝗻 𝗼𝘂𝘁𝗯𝗼𝘂𝗻𝗱 𝗿𝗲𝗾𝘂𝗲𝘀𝘁𝘀 ↳ HttpClient calls hang forever waiting for responses ↳ Resource exhaustion brings down your entire service ✅ Set HttpClient .Timeout and use CancellationTokenSource with timeout 𝟰/ 𝗡𝗼𝘁 𝗺𝗮𝗸𝗶𝗻𝗴 𝘁𝗵𝗲 𝗲𝗻𝘁𝗶𝗿𝗲 𝗰𝗮𝗹𝗹 𝗰𝗵𝗮𝗶𝗻 𝗮𝘀𝘆𝗻𝗰 ↳ Mixing sync/async patterns breaks everything ↳ Deadlocks and poor scalability under load ✅ Go async all the way: controller → service → repository 𝟱/ 𝗨𝘀𝗶𝗻𝗴 𝗧𝗮𝘀𝗸.𝗥𝘂𝗻 𝗶𝗻𝘀𝗶𝗱𝗲 𝗰𝗼𝗻𝘁𝗿𝗼𝗹𝗹𝗲𝗿𝘀/𝘀𝗲𝗿𝘃𝗶𝗰𝗲𝘀 ↳ Offloading I/O work to thread pool unnecessarily ↳ Context switching overhead kills performance ✅ Use Task .Run only for CPU-intensive work, not I/O operations 𝟲/ 𝗕𝘂𝗳𝗳𝗲𝗿𝗶𝗻𝗴 𝗵𝘂𝗴𝗲 𝗽𝗮𝘆𝗹𝗼𝗮𝗱𝘀 𝗶𝗻𝘀𝘁𝗲𝗮𝗱 𝗼𝗳 𝘀𝘁𝗿𝗲𝗮𝗺𝗶𝗻𝗴 ↳ Loading 500MB responses into memory at once ↳ OutOfMemoryException crashes your app ✅ Use IAsyncEnumerable and Stream .CopyToAsync instead 𝟳/ 𝗨𝘀𝗶𝗻𝗴 𝗧𝗮𝘀𝗸.𝗪𝗵𝗲𝗻𝗔𝗹𝗹 𝘄𝗶𝘁𝗵𝗼𝘂𝘁 𝗹𝗶𝗺𝗶𝘁𝘀 ↳ Firing 1000 concurrent requests to external APIs ↳ Rate limiting and cascade failures ✅ Control concurrency with small chunks or Parallel .ForEachAsync 𝟴/ 𝗧𝗵𝗲 𝗮𝘀𝘆𝗻𝗰 𝘃𝗼𝗶𝗱 𝘁𝗿𝗮𝗽 ↳ async void methods outside event handlers ↳ Unhandled exceptions crash your entire process ✅ Always return Task or Task<T> from async methods 𝟵/ 𝗙𝗶𝗿𝗲-𝗮𝗻𝗱-𝗳𝗼𝗿𝗴𝗲𝘁 𝗱𝗶𝘀𝗮𝘀𝘁𝗲𝗿𝘀 ↳ Starting background tasks without proper tracking ↳ Silent failures and resource leaks everywhere ✅ Use OutBox or BackgroundService to process background tasks 𝟭𝟬/ 𝗠𝗶𝘀𝘀𝗶𝗻𝗴 𝗖𝗼𝗻𝗳𝗶𝗴𝘂𝗿𝗲𝗔𝘄𝗮𝗶𝘁(𝗳𝗮𝗹𝘀𝗲) ↳ Library code captures synchronization context unnecessarily ✅ Use ConfigureAwait(false) in all library async methods 👉 Join 𝟭𝟱,𝟬𝟬𝟬+ people in my .NET Newsletter. Weekly best practices, real-world examples, and pro tips to craft better software today! 𝗕𝗼𝗻𝘂𝘀: every subscriber gets a PDF with 650+ exclusive resources for mastering C#, .NET, ASP .NET Core, EF Core, and Microservices. — ♻️ Repost to help others avoid common async mistakes ➕ Follow me ( Anton Martyniuk ) to improve your .NET Skills

  • View profile for Ayman Anaam

    Dynamic Technology Leader | Innovator in .NET Development and Cloud Solutions

    11,632 followers

    Tired of Waiting for All Tasks to Complete? Meet Task.WaitAny! Imagine you’re making multiple API calls or querying multiple databases at the same time. Instead of waiting for all tasks to finish, what if you could process results as soon as the first one completes? That’s exactly what Task.WaitAny helps with! The Problem You have multiple asynchronous operations running, but you don’t need to wait for all of them to complete before taking action. ❌ Bad Approach – Blocking Until All Tasks Finish 𝐓𝐚𝐬𝐤.𝐖𝐚𝐢𝐭𝐀𝐥𝐥(𝐭1, 𝐭2, 𝐭3); // 𝐁𝐥𝐨𝐜𝐤𝐬 𝐮𝐧𝐭𝐢𝐥 𝐀𝐋𝐋 𝐭𝐚𝐬𝐤𝐬 𝐟𝐢𝐧𝐢𝐬𝐡 Issue: If one task takes significantly longer than the others, everything is delayed unnecessarily. ✅ The Solution – Process the First Completed Task with Task.WaitAny 𝐢𝐧𝐭 𝐜𝐨𝐦𝐩𝐥𝐞𝐭𝐞𝐝𝐈𝐧𝐝𝐞𝐱 = 𝐓𝐚𝐬𝐤.𝐖𝐚𝐢𝐭𝐀𝐧𝐲(𝐭𝐚𝐬𝐤𝐬); Why Use Task.WaitAny? ✅ Faster Response Times – You can process results as soon as one task completes. ✅ Efficient Resource Use – No unnecessary waiting for slower tasks. ✅ Better User Experience – Improves responsiveness in UI and web apps (when used correctly). When to Use Task.WaitAny? ▪️ Handling multiple API calls and processing the first available response. ▪️ Running background jobs where you don’t need all tasks to complete. ▪️ Load balancing tasks and using the first available result. Tip: Process Tasks as They Complete Want to process each completed task as soon as it's done? Use a loop with Task.WaitAny to handle them one by one. ⚠️ Key Considerations 1. Blocking Behavior: ▪️ Task.WaitAny blocks the current thread. Avoid in UI/web apps. ▪️ Use await Task.WhenAny for non-blocking behavior in async apps. 2. Error Handling: ▪️ Always check task.IsFaulted to handle exceptions. When to Use? ▪️ Task.WaitAny: Console apps, background services. ▪️ Task.WhenAny: UI/web apps for non-blocking async operations. Have you used Task.WaitAny or Task.WhenAny? Share your tips below!

  • View profile for Hasnain Ahmad

    Senior Software Engineer @ PostEx | React | Angular | Node.js | TypeScript

    2,492 followers

    I remember a junior developer on my team once came to me, frustrated that an API call was taking way too long — around 19 seconds in total. He was using async/await and assumed it was automatically the most efficient approach. But when I looked at the code, I immediately spotted the issue: const res1 = await fetchA(); const res2 = await fetchB(); const res3 = await fetchC(); Each call was waiting for the previous one to finish — completely sequential. No wonder it was slow. I suggested a small change that made a huge impact: const [res1, res2, res3] = await Promise.all([ fetchA(), fetchB(), fetchC(), ]); Just like that, the total response time dropped from 19 seconds to just 90ms. All because the API calls started running in parallel, not one after the other. Key takeaway: Using async/await doesn’t automatically mean your code is fast. When your async calls don’t depend on each other, Promise.all() can make a night-and-day difference. I love moments like these — small tweaks, big wins. Have you ever made (or fixed) a similar async/await mistake? Would love to hear! #FreelanceDeveloper #FullStackDeveloper #JavaScriptDeveloper #ReactJS #AngularDeveloper #NodeJS #WebAppDevelopment #RemoteDeveloper #TechTips

  • View profile for Carl-Hugo Marcotte

    Author of Architecting ASP.NET Core Applications: An Atypical Design Patterns Guide for .NET 8, C# 12, and Beyond | Software Craftsman | Principal Architect | .NET/C# | AI

    8,726 followers

    🚀 Boosting Performance with C# Parallel.ForEach[Async] 🚀 When dealing with multiple I/O-bound operations—like HTTP requests to a REST API—sequential execution (`foreach`) can slow down performance significantly. Fortunately, `Parallel.ForEach` and `Parallel.ForEachAsync` allow us to execute these operations concurrently, unlocking massive speed improvements. 🔥 The Problem: Sequential Execution Consider the scenario where we need to make N remote calls where N=6. Assuming the remote endpoint takes 2 seconds to respond, using a `foreach` loop will take 12 seconds to complete (left code). Borrowing from the big O notation, this runs in O(N) time, meaning the time is linearly relative to the number of iterations (N), so 100 calls would take around 200 seconds (over 3 minutes) to complete, which is enormous. ⚡ The Solution: Parallel Execution With `Parallel.ForEachAsync`, we can execute the calls in parallel. Assuming the server has enough resources to send the N requests simultaneously, it would take only about 2 seconds to complete the execution of the endpoint, no matter what the value of N is (right code). In big O terms, this runs in O(1) time, meaning the time it takes to complete the execution is constant and will always be the same (a.k.a. two seconds). Since we live in a discreet world, we do not have unlimited resources, so the actual execution time would be O(N/k), where k is the MaxDegreeOfParallelism (a.k.a. the maximum number of calls we can do at once). 📊 Results—100 remote calls using my personal computer 🏆 `Parallel.ForEachAsync`: 10.2095184 seconds. 😞 `foreach` loop: 3:20.9339857 minutes. 📖 Conclusion While `Parallel.ForEachAsync` can dramatically reduce execution time, the real-world performance boost depends on the system's ability to handle parallel execution. ✅ Ideal for independent I/O-bound operations like HTTP requests. ✅ Use MaxDegreeOfParallelism to control how many requests to send in parallel. ✅ Be cautious of shared state (e.g., List<T>)—use thread-safe collections like ConcurrentBag<T> instead. 📌 Tip You can use `Parallel.ForEach` to execute synchronous operations in parallel, while `Parallel.ForEachAsync` allows you to use async/await code. 💬 What’s your experience with parallel execution? Have you tried `Parallel.ForEachAsync`, or do you have a different approach? Do you have stories to share? Drop your thoughts in the comments! 🚀👇 #ParallelProgramming #Performance #ASPNETCore #SoftwareArchitecture #dotnet #csharp #DesignAndArchitecture #CodeDesign #ProgrammingTips #CleanCode

Explore categories