Skip to content

Signal Completion is missing documentation about stopping host for non-success scenarios #45902

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
sander1095 opened this issue Apr 23, 2025 · 3 comments
Assignees
Labels
dotnet-fundamentals/svc 📌 seQUESTered Identifies that an issue has been imported into Quest.

Comments

@sander1095
Copy link

sander1095 commented Apr 23, 2025

Type of issue

Missing information

Description

Hi!

I'm currently building an Azure Container App Job. I've built these as Console Apps before, but I'm now looking into using Worker Service instead as they set up the generic host and other goodness for me out of the box.

I need the app to start up, run some code, and then exit, so the process isn't long-lived. This is easy with the Console App; when it runs out of code to run, it just exits ;). It might be that I shouldn't be using worker services in my scenario, but I think it's a good question to ask anyway!

Like the documentation says, you need to stop the host by Signalling completion in a Worker Service. However, this will end the application with a succes code.

My question: How do you stop a host from inside a hosted service and signal that we're exiting because of an error?

For example, we're running some code in the Hosted Service and something goes wrong. Naturally, I want to exit with an exit code. However, HostApplicationLifetime.StopApplication(); doesn't support this.

There are other ways (Environment.Exit(1); comes to mind) but I am not sure if this is recommended.

Therefore, some more information about exiting a worker service with an error code from inside a hosted service would be great!

Page URL

https://learn.microsoft.com/en-us/dotnet/core/extensions/workers

Content source URL

https://github.com/dotnet/docs/blob/main/docs/core/extensions/workers.md

Document Version Independent Id

ff379d26-0d85-6d74-67da-4a3cd260b04d

Platform Id

4a2c295f-6871-5e01-01ea-ec1779c4558c

Article author

@IEvangelist

Metadata

  • ID: ae847f16-ff74-ab68-7163-f713b447430c
  • PlatformId: 4a2c295f-6871-5e01-01ea-ec1779c4558c
  • Service: dotnet-fundamentals

Related Issues


Associated WorkItem - 424099

@IEvangelist
Copy link
Member

IEvangelist commented Apr 23, 2025

Hi there @sander1095 - thank you for posting this issue, much appreciated. Yeah, that is a good question. I detailed hosted scenario shutdowns here: https://learn.microsoft.com/en-us/dotnet/core/extensions/generic-host?tabs=appbuilder#host-shutdown. Be forewarned, there's a lot of things to think about.

Your general question though is about whether or not you should be using the worker template for a short-lived app, I would argue no. Instead, simply use a generic host with a console app. Unfortunately, there isn't a template for that and even our docs on the subject do show a worker scenario, but you don't need a worker.

See: https://learn.microsoft.com/dotnet/core/extensions/generic-host

This would do the job, example project:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net9.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.Extensions.Hosting" Version="9.0.4" />
  </ItemGroup>

</Project>

Example program:

using Microsoft.Extensions.Hosting;

var builder = Host.CreateApplicationBuilder(args);

// Add services for DI:
// builder.Services.AddSingleton<IFoo, Foo>();

using var app = builder.Build();

// Get services and do logic:
// var foo = app.Services.GetRequiredService<IFoo>();
// foo.DoSomething();

await app.RunAsync();

Does that make sense? You end up with all the goodies you mentioned, but without the complexity of attempting to signal shutdown.

@IEvangelist IEvangelist self-assigned this Apr 23, 2025
@IEvangelist IEvangelist added the 🗺️ reQUEST Triggers an issue to be imported into Quest. label Apr 23, 2025
@dotnet-policy-service dotnet-policy-service bot removed the ⌚ Not Triaged Not triaged label Apr 23, 2025
@dotnetrepoman dotnetrepoman bot added the 🗺️ mapQUEST Only used as a way to mark an issue as updated for quest. RepoMan should instantly remove it. label Apr 23, 2025
@dotnet-policy-service dotnet-policy-service bot removed the 🗺️ mapQUEST Only used as a way to mark an issue as updated for quest. RepoMan should instantly remove it. label Apr 23, 2025
@sander1095
Copy link
Author

Hi @IEvangelist !

Thanks for your reply. My main suggestions for doc improvements still stand, where the user might want to learn how to exit a hosted service and host with an exit code.

About your comments: What would adding await app.RunAsync() do in your example? Considering we want to exit the app after executing the code.

@sequestor sequestor bot added 📌 seQUESTered Identifies that an issue has been imported into Quest. and removed 🗺️ reQUEST Triggers an issue to be imported into Quest. labels Apr 24, 2025
@IEvangelist
Copy link
Member

What would adding await app.RunAsync() do in your example? Considering we want to exit the app after executing the code.

It runs the app and waits for the app to be ended, like SIGTERM.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
dotnet-fundamentals/svc 📌 seQUESTered Identifies that an issue has been imported into Quest.
Projects
Status: 🔖 Ready
Development

No branches or pull requests

2 participants