Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why I can stop an IHostedService when therre are background threads running?

Tags:

c#

.net

Below is my simple code that runs an 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;
   }
}

So when I want to stop the service by pressing ctrl + C in the console, I exepct to see the service stops and console prints "Stopping service".

But when I press Ctrl + C, the service continues running in the infinite loop, which I don't understand.

I think Task.Run() queues a work item on the thread pool, then a background thread from thread pool to pick up the job, so in my example, it is a worker thread (worker thread's id is 4, main thread's id is 1) that executes the while loop. So when I press ctrl + S, the service should stop, then why the running background thread stops the service being stopped, isn't that when a application terminals, all background jobs/ threads terminates too? I mean if Task.Run() runs creates a foreground threads then I can understand, because all foreground threads need to finish before the applciation could be stopped.

P.S:

I can pass the CancellationTokento stop the while loop, I understand I can do that and in the while loop, I check if the token is cancalled etc...

but I don't understand why I have to do that, because the running thread is a background thread, not a foreground thread, so why all background threads need to finish first the the StopAsync() can be invoked? i.e how does a running background thread stops the exection flow reach to StopAsync()?


1 Answers

If you want to stop a Task try using a cancellation token in MyServiceClass

Here is my example:

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;
    }
}
like image 92
Mgu Avatar answered Nov 26 '25 10:11

Mgu



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!