如何使持久性后台任务在 asp.net 核心中发出范围服务信号?
How to make a persistent background task signal a scoped service in asp.net core?
在我的 ASP.NET Core 2.2 Web 应用程序中,我的 Startup.ConfigureServices(IServiceCollection services) 方法中有这些作用域服务:
public void ConfigureServices(IServiceCollection services)
{
services.AddDirectoryBrowser();
services.AddScoped<WebApplication.Services.DoThingAlpha>();
services.AddScoped<WebApplication.Services.DoThingBravo>();
services.AddScoped<WebApplication.Services.DoThingCharlie>();
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}
这些范围内的服务为我的控制器做脏活。
但是,我需要在后台持续侦听 UDP 端口,然后在侦听器上收到某些 UDP 消息时通知相应的服务(DoThingsAlpha、DoThingsBravo 或 DoThingsCharlie)。
我想我可以用BackgroundService(https://docs.microsoft.com/en-us/dotnet/standard/microservices-architecture/multi-container-microservice-net-applications/background-tasks-with-ihostedservice)实现后台服务,然后添加到ConfigureServices中的服务集合。让我们称之为 ListenOnUDP : BackgroundService
问题是,我如何向其他范围内的服务发送信号,告知在 ListenOnUDP 中收到了 UDP 消息?解决此类问题的推荐模式是什么?肯定有。
我已经制定了解决方案,我认为问题源于我对 ASP.NET 核心服务根本缺乏了解。我会解释以防有人遇到同样的问题(或者可能使我的回答有效或无效)。
当您将服务 class/interface 添加到 IServiceCollection 时,其他服务可以通过该接口访问该服务。您只需将接口包含在您要在构造函数中调用的其他服务的构造函数中,保存它,然后您就可以调用该接口(我理解的是依赖注入的表现)。像这样:
private readonly InterfaceRCResponseQueue _rcResponseQueue;
private readonly ILogger _logger;
public UdpListenerBackgroundService(
InterfaceRCResponseQueue rcResponseQueue,
ILogger<UdpListenerBackgroundService> logger
)
{
_rcResponseQueue = rcResponseQueue;
_logger = logger;
}
这有效地让一个服务通过调用接口上的方法向另一个服务发出信号。
收获:
单例服务不能依赖于作用域或瞬态服务。大概是因为它挂断了作用域或瞬态服务。反之亦然。
https://blog.markvincze.com/two-gotchas-with-scoped-and-singleton-dependencies-in-asp-net-core/
就我而言,我有一个 UdpClient class 需要侦听消息然后向其他服务发送信号。
为此,我将我的 UdpClient class 放在继承自 Microsoft.Extensions.Hosting.BackgroundService 的 class 中,因此随着应用程序的生命周期而创建和拆除。我还创建了一个包含队列的单例 class。
当我的 BackgroundService class 中的 UdpClient class 获取 UDP 数据报时,我在单例 class 上调用一个方法,将其排入单例 class'排队。
作用域、单例或瞬态 class 然后可以依赖于单例 class 并在闲暇时在该队列中查找数据(出列)。你不能做相反的事情(使单例依赖于作用域或传递服务)。
这是我想出的信号形式,用于从单例或后台服务间接通知较小的服务。
在我的 ASP.NET Core 2.2 Web 应用程序中,我的 Startup.ConfigureServices(IServiceCollection services) 方法中有这些作用域服务:
public void ConfigureServices(IServiceCollection services)
{
services.AddDirectoryBrowser();
services.AddScoped<WebApplication.Services.DoThingAlpha>();
services.AddScoped<WebApplication.Services.DoThingBravo>();
services.AddScoped<WebApplication.Services.DoThingCharlie>();
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}
这些范围内的服务为我的控制器做脏活。
但是,我需要在后台持续侦听 UDP 端口,然后在侦听器上收到某些 UDP 消息时通知相应的服务(DoThingsAlpha、DoThingsBravo 或 DoThingsCharlie)。
我想我可以用BackgroundService(https://docs.microsoft.com/en-us/dotnet/standard/microservices-architecture/multi-container-microservice-net-applications/background-tasks-with-ihostedservice)实现后台服务,然后添加到ConfigureServices中的服务集合。让我们称之为 ListenOnUDP : BackgroundService
问题是,我如何向其他范围内的服务发送信号,告知在 ListenOnUDP 中收到了 UDP 消息?解决此类问题的推荐模式是什么?肯定有。
我已经制定了解决方案,我认为问题源于我对 ASP.NET 核心服务根本缺乏了解。我会解释以防有人遇到同样的问题(或者可能使我的回答有效或无效)。
当您将服务 class/interface 添加到 IServiceCollection 时,其他服务可以通过该接口访问该服务。您只需将接口包含在您要在构造函数中调用的其他服务的构造函数中,保存它,然后您就可以调用该接口(我理解的是依赖注入的表现)。像这样:
private readonly InterfaceRCResponseQueue _rcResponseQueue;
private readonly ILogger _logger;
public UdpListenerBackgroundService(
InterfaceRCResponseQueue rcResponseQueue,
ILogger<UdpListenerBackgroundService> logger
)
{
_rcResponseQueue = rcResponseQueue;
_logger = logger;
}
这有效地让一个服务通过调用接口上的方法向另一个服务发出信号。
收获:
单例服务不能依赖于作用域或瞬态服务。大概是因为它挂断了作用域或瞬态服务。反之亦然。
https://blog.markvincze.com/two-gotchas-with-scoped-and-singleton-dependencies-in-asp-net-core/
就我而言,我有一个 UdpClient class 需要侦听消息然后向其他服务发送信号。
为此,我将我的 UdpClient class 放在继承自 Microsoft.Extensions.Hosting.BackgroundService 的 class 中,因此随着应用程序的生命周期而创建和拆除。我还创建了一个包含队列的单例 class。
当我的 BackgroundService class 中的 UdpClient class 获取 UDP 数据报时,我在单例 class 上调用一个方法,将其排入单例 class'排队。
作用域、单例或瞬态 class 然后可以依赖于单例 class 并在闲暇时在该队列中查找数据(出列)。你不能做相反的事情(使单例依赖于作用域或传递服务)。
这是我想出的信号形式,用于从单例或后台服务间接通知较小的服务。