Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

379
Views
¿Por qué puedo detener un IHostedService cuando hay subprocesos en segundo plano ejecutándose?

A continuación se muestra mi código simple que ejecuta un IHostedService

 internal class Program { public static Task Main(string[] args) { var host = new HostBuilder().ConfigureServices((hostcontext, services) => { services.AddHostedService<MyService>(); }).Build(); host.Run(); return Task.CompletedTask; } } public class MyService : IHostedService { public Task StartAsync(CancellationToken cancellationToken) { return Task.Run(() => { while (true) { Console.WriteLine("Starting Service"); } }); } public Task StopAsync(CancellationToken cancellationToken) { Console.WriteLine("Stopping service"); return Task.CompletedTask; } }

Entonces, cuando quiero detener el servicio presionando ctrl + C en la consola, espero ver que el servicio se detiene y la consola imprime "Deteniendo el servicio".

Pero cuando presiono Ctrl + C, el servicio continúa ejecutándose en el ciclo infinito, lo cual no entiendo.

Creo que Task.Run() en cola un elemento de trabajo en el grupo de subprocesos, luego un subproceso de fondo del grupo de subprocesos para retomar el trabajo, por lo que en mi ejemplo, es un subproceso de trabajo (la identificación del subproceso de trabajo es 4, la identificación del subproceso principal es 1) que ejecuta el ciclo while. Entonces, cuando presiono ctrl + S, el servicio debe detenerse, entonces, ¿por qué el subproceso en segundo plano en ejecución detiene el servicio? ¿No es eso cuando una aplicación termina, todos los trabajos/subprocesos en segundo plano también finalizan? Quiero decir, si Task.Run() se ejecuta crea subprocesos en primer plano, entonces puedo entender, porque todos los subprocesos en primer plano deben finalizar antes de que se pueda detener la aplicación.

PD:

Puedo pasar CancellationToken para detener el ciclo while, entiendo que puedo hacer eso y en el ciclo while, compruebo si se puede llamar al token, etc.

pero no entiendo por qué tengo que hacer eso, porque el subproceso en ejecución es un subproceso de fondo, no un subproceso de primer plano, entonces, ¿por qué todos los subprocesos de fondo deben terminar primero y se puede invocar StopAsync() ? es decir , ¿cómo un subproceso en segundo plano en ejecución detiene el flujo de ejecución que llega a StopAsync() ?

over 4 years ago · Santiago Trujillo
2 answers
Answer question

0

Si desea detener una tarea, intente usar un token de cancelación en MyServiceClass

Aquí está mi ejemplo:

 public class MyService : IHostedService { private CancellationTokenSource _ts; public Task StartAsync(CancellationToken cancellationToken) { _ts = new CancellationTokenSource(); return Task.Factory.StartNew(() => { while (true) { Console.WriteLine("Starting Service"); Thread.Sleep(500); if (_ts.Token.IsCancellationRequested) { Console.WriteLine("Stopping service"); break; } } }, _ts.Token); } public Task StopAsync(CancellationToken cancellationToken) { _ts.Cancel(); return Task.CompletedTask; } }
over 4 years ago · Santiago Trujillo Report

0

La razón por la que Ctrl+C no finaliza directamente la aplicación de la consola, como podría estar acostumbrado desde las aplicaciones de consola "ordinarias", es que en realidad hay soporte en .NET para evitar que Ctrl+C finalice la aplicación, y para la aplicación para reaccionar a Ctrl+C y "hacer cosas".

El marco de alojamiento que está utilizando ha utilizado este sistema, un evento, para evitar que su aplicación se termine por la fuerza, así como para asumir el procedimiento de apagado.

El evento en sí es Console.CancelKeyPress y este es un evento cancelable, lo que significa que puede regresar desde el controlador de eventos y establecer una marca en el objeto EventArgs para indicarle al código que invocó su controlador de eventos que desea cancelar el manejo predeterminado de Ctrl+C.

El marco de alojamiento ha hecho esto.

Puede ver el código exacto aquí: Microsoft.Extensions.Hosting/Internal/ConsoleLifetime.cs @48-52 :

 Console.CancelKeyPress += (sender, e) => { e.Cancel = true; ApplicationLifetime.StopApplication(); };

Además de cancelar el procedimiento de apagado normal, el controlador de eventos proporcionado por el marco de alojamiento también cancela un CancellationToken que es el token que se pasa a StartAsync. Como usted dice, si pasa este token a sus tareas y reacciona ante su cancelación, su aplicación se cierra.

La llamada a ApplicationLifetime.StopApplication eventualmente termina en Microsoft.Extensions.Hosting/Internal/ApplicationLifetime.cs @102-112 :

 private void ExecuteHandlers(CancellationTokenSource cancel) { // Noop if this is already cancelled if (cancel.IsCancellationRequested) { return; } // Run the cancellation token callbacks cancel.Cancel(throwOnFirstException: false); }

Así que ahí lo tienes. La razón por la que su aplicación sigue girando en un ciclo infinito es precisamente porque el marco de alojamiento evita el apagado normal y, en cambio, le da a sus tareas la oportunidad de completarse de manera ordenada. Dado que sus tareas ignoran esta solicitud y siguen ejecutándose, su proceso nunca termina cuando presiona Ctrl+C.

over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!