c# - 为什么当有后台线程运行时我可以停止 IHostedService?

标签 c# .net

下面是我运行 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;
   }
}

因此,当我想通过在控制台中按 ctrl + C 来停止服务时,我期望看到服务停止并且控制台打印“正在停止服务”。

但是当我按 Ctrl + C 时,服务继续在无限循环中运行,我不明白。

我认为 Task.Run() 在线程池上排队一个工作项,然后从线程池中派出一个后台线程来获取作业,所以在我的示例中,它是一个工作线程(工作线程的id是4,主线程的id是1)执行while循环。因此,当我按 ctrl + S 时,服务应该停止,那么为什么正在运行的后台线程会停止正在停止的服务,不是当应用程序终止时,所有后台作业/线程也会终止吗?我的意思是,如果 Task.Run() 运行创建了一个前台线程,那么我可以理解,因为所有前台线程都需要在应用程序停止之前完成。

附注:

我可以传递 CancellationToken 来停止 while 循环,我知道我可以做到这一点,并且在 while 循环中,我检查 token 是否被取消等...

但我不明白为什么我必须这样做,因为正在运行的线程是后台线程,而不是前台线程,所以为什么所有后台线程都需要首先完成 StopAsync() 可以被调用吗?正在运行的后台线程如何停止到达StopAsync()的执行流?

最佳答案

如果您想停止任务,请尝试在 MyServiceClass 中使用取消 token

这是我的例子:

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;
    }
}

关于c# - 为什么当有后台线程运行时我可以停止 IHostedService?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71110959/

相关文章:

c# - 使用 C# 如何检测是否安装了 Windows Installer 4.5

c# - 无法将 lambda 表达式转换为类型 'System.Delegate',因为它不是委托(delegate)类型

c# - 在 C# 中获取局域网的计算机名称

c# - Observable.ObserveOn() 似乎没有效果

c# - 将 outerXml 转换为 OpenXmlElement

c# - TopShelf 服务在异常时卡在 'Stopping' 状态

c# - 在代码 C# 中将标签字体更改为粗体

c# - System.IO.FileLoadException - 无法加载文件或程序集 Microsoft.WindowsAzure.Storage

c# - .NET 中的 JSON 反序列化

c# - .NET正则表达式:内联大小写不起作用