DEV Community

Cover image for Why Your .NET Application Works in an IDE but Fails in CI/CD or Terminal: Understanding Asynchronous Execution
Laura Pučkoriūtė
Laura Pučkoriūtė

Posted on

1 1

Why Your .NET Application Works in an IDE but Fails in CI/CD or Terminal: Understanding Asynchronous Execution

Yup, I missed an await .

Nothing new. No one else to blame.

But why did it take so long to find it? Because the app worked locally but failed on the pipeline, I thought it was a pipeline problem! Is the Azure pipeline set up in some way that doesn’t wait for my dotnet run command to finish? Does an error occur that is not properly logged and therefore not visible on the pipeline run? Do I need to use a different Azure DotNetCoreCLI task or instead start the program with a shell script? Am I losing my mind?

Asynchronous programming can be tricky, especially when tasks are not awaited properly. This often leads to unexpected behavior, especially when running applications in different environments (like Rider or other IDEs vs. the terminal or CI/CD pipelines).

My case

static void Main(string[] args)
{
    SomeProcess(); // Missing await
}

static async Task SomeProcess() {
    await SomeOtherProcess();
}
Enter fullscreen mode Exit fullscreen mode

My Main function called a process that had a few asynchronous tasks. On the pipeline, observing the logs, I saw that the pipeline task running the program would be completed at random times, rarely letting the .NET program complete a full run.

That is because the call in the Main function to a process initiating asynchronous tasks never waited for that process to complete, and the Main function run finished whenever it pleased.

But why did the .NET program always run fully in the Rider IDE?

Seems like Rider might have a specific run environment. Rider might implicitly handle unawaited tasks, potentially waiting for asynchronous tasks to complete before terminating the run process, allowing the app to seem to run fully. An IDE might introduce additional debugging or process-wait mechanisms that make the application appear to be more forgiving in certain cases.

When running in the terminal or CI/CD pipelines, there is no "help" from Rider or other IDEs. The application exits immediately after the Main method finishes, even if tasks are still running in the background. Without await, these background tasks won’t finish before the application ends, leading to errors or incomplete operations.

How I fixed it

First, it was important to start my application by running the dotnet run command from the terminal, and not an IDE. This way it was clear that the problem was in the application code, not in my pipeline setup.

Then, I had to dig a bit through the code to find where exactly I was not handling the asynchronous processes properly. Once I found it, I added the missing await statement. And it worked like magic.

static async Task Main(string[] args)
{
    await SomeProcess();
}

static async Task SomeProcess() {
    await SomeOtherProcess();
}
Enter fullscreen mode Exit fullscreen mode

Lessons learned

  • Always await asynchronous operations.
  • Test in multiple environments: test the run of your application in a terminal or similar environment to where it is failing.
  • Do not rely just on the IDE run processes to verify the functionality of your program.

Image of Docusign

🛠️ Bring your solution into Docusign. Reach over 1.6M customers.

Docusign is now extensible. Overcome challenges with disconnected products and inaccessible data by bringing your solutions into Docusign and publishing to 1.6M customers in the App Center.

Learn more

Top comments (0)

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more

👋 Kindness is contagious

Discover a treasure trove of wisdom within this insightful piece, highly respected in the nurturing DEV Community enviroment. Developers, whether novice or expert, are encouraged to participate and add to our shared knowledge basin.

A simple "thank you" can illuminate someone's day. Express your appreciation in the comments section!

On DEV, sharing ideas smoothens our journey and strengthens our community ties. Learn something useful? Offering a quick thanks to the author is deeply appreciated.

Okay