.NET 5.0 和 6.0,后台服务不会像来自 MS 的示例那样停止
.NET 5.0 and 6.0, background service not stopping like samples from MS
简而言之,我正在为一个简单的数据库进程构建一个 TCP 服务器。我查看了后台服务的 MS 样本,特别是 App.WorkerService.
到目前为止一切顺利,可以 运行 服务并且每个应用程序实例只启动一次 TCP 服务器。
现在我想在用户 window 命令 运行ning 中按下键盘上的 [ESC]ape 键时停止服务。
这里是 Program.cs:
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
namespace PostDataService
{
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureServices((hostContext, services) =>
{
services.AddHostedService<Worker>();
});
}
}
这是工人class:
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using System;
using System.Threading;
using System.Threading.Tasks;
using WatsonTcp;
namespace PostDataService
{
public class Worker : BackgroundService
{
private readonly ILogger<Worker> _logger;
private int _serverPort = 1701;
private static WatsonTcpServer _Server;
public Worker(ILogger<Worker> logger)
{
_logger = logger;
_Server = new(null, _serverPort);
_Server.Events.ClientConnected += ClientConnected;
_Server.Events.ClientDisconnected += ClientDisconnected;
_Server.Events.MessageReceived += MsgReceived;
_Server.Start();
}
private void MsgReceived(object sender, MessageReceivedEventArgs args)
{
Console.WriteLine("Got Msg");
}
private void ClientDisconnected(object sender, DisconnectionEventArgs args)
{
throw new NotImplementedException();
}
private void ClientConnected(object sender, ConnectionEventArgs args)
{
throw new NotImplementedException();
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
_logger.LogInformation("Worker running at: {time} {threadid}", DateTimeOffset.Now, Thread.CurrentThread.ManagedThreadId );
await Task.Delay(500, stoppingToken);
}
_Server.Stop();
}
}
}
那么如何将 stoppingToken.IsCancellationRequested 设置为 true?
停止控制台应用程序的快捷方式是 Ctrl+C 而不是 Esc。如果您仍希望 Esc 正常工作,您可以这样做:
IHost host = Host.CreateDefaultBuilder(args)
.ConfigureServices(services =>
{
services.AddHostedService<Worker>();
})
.Build();
var hostTask = host.RunAsync();
// listen for Esc
_ = Task.Run(async () =>
{
ConsoleKeyInfo key;
do
{
key = Console.ReadKey();
}
while (key.Key != ConsoleKey.Escape);
await host.StopAsync();
});
await hostTask;
我还建议在您的 Worker
:
中添加类似的内容
public override Task StopAsync(CancellationToken cancellationToken)
{
_logger.LogInformation("stopping server");
_Server.Stop();
return Task.CompletedTask;
}
简而言之,我正在为一个简单的数据库进程构建一个 TCP 服务器。我查看了后台服务的 MS 样本,特别是 App.WorkerService.
到目前为止一切顺利,可以 运行 服务并且每个应用程序实例只启动一次 TCP 服务器。
现在我想在用户 window 命令 运行ning 中按下键盘上的 [ESC]ape 键时停止服务。
这里是 Program.cs:
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
namespace PostDataService
{
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureServices((hostContext, services) =>
{
services.AddHostedService<Worker>();
});
}
}
这是工人class:
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using System;
using System.Threading;
using System.Threading.Tasks;
using WatsonTcp;
namespace PostDataService
{
public class Worker : BackgroundService
{
private readonly ILogger<Worker> _logger;
private int _serverPort = 1701;
private static WatsonTcpServer _Server;
public Worker(ILogger<Worker> logger)
{
_logger = logger;
_Server = new(null, _serverPort);
_Server.Events.ClientConnected += ClientConnected;
_Server.Events.ClientDisconnected += ClientDisconnected;
_Server.Events.MessageReceived += MsgReceived;
_Server.Start();
}
private void MsgReceived(object sender, MessageReceivedEventArgs args)
{
Console.WriteLine("Got Msg");
}
private void ClientDisconnected(object sender, DisconnectionEventArgs args)
{
throw new NotImplementedException();
}
private void ClientConnected(object sender, ConnectionEventArgs args)
{
throw new NotImplementedException();
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
_logger.LogInformation("Worker running at: {time} {threadid}", DateTimeOffset.Now, Thread.CurrentThread.ManagedThreadId );
await Task.Delay(500, stoppingToken);
}
_Server.Stop();
}
}
}
那么如何将 stoppingToken.IsCancellationRequested 设置为 true?
停止控制台应用程序的快捷方式是 Ctrl+C 而不是 Esc。如果您仍希望 Esc 正常工作,您可以这样做:
IHost host = Host.CreateDefaultBuilder(args)
.ConfigureServices(services =>
{
services.AddHostedService<Worker>();
})
.Build();
var hostTask = host.RunAsync();
// listen for Esc
_ = Task.Run(async () =>
{
ConsoleKeyInfo key;
do
{
key = Console.ReadKey();
}
while (key.Key != ConsoleKey.Escape);
await host.StopAsync();
});
await hostTask;
我还建议在您的 Worker
:
public override Task StopAsync(CancellationToken cancellationToken)
{
_logger.LogInformation("stopping server");
_Server.Stop();
return Task.CompletedTask;
}