gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-03 08:09:59 25 4
gpt4 key购买 nike

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

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com