C# 使用作用域服务的Websocket单例

C# 使用作用域服务的Websocket单例,c#,dependency-injection,websocket,.net-core,middleware,C#,Dependency Injection,Websocket,.net Core,Middleware,我已经实现了WebSocket中间件,它包含一个字段singleton WebSocket字典(通过构造函数注入)和一些其他通过构造函数注入的作用域参数 我想知道它是否正确实施 public WebSocketManagerMiddleware(RequestDelegate next, IWebSocketConnectionDictionary webSocketDictionary, IScopedServiceOne scopedOneService, IScopedSe

我已经实现了WebSocket中间件,它包含一个字段singleton WebSocket字典(通过构造函数注入)和一些其他通过构造函数注入的作用域参数

我想知道它是否正确实施

public WebSocketManagerMiddleware(RequestDelegate next,
    IWebSocketConnectionDictionary webSocketDictionary,
    IScopedServiceOne scopedOneService, IScopedServiceTwo scopedtwoService)
{
    _next = next;
    _webSocketManager = webSocketDictionary;
    _scopedOneService= scopedOneService;
    _scopedtwoService= scopedtwoService;
}
对于此构造函数,我将如下方式注入这些实例:

_app.UseMiddleware<WebSocketManagerMiddleware>(
    app.ApplicationServices.GetWebSocketConnectionDictionary(),
    serviceProvider.CreateScope().ServiceProvider.GetScopedOneService(),
    serviceProvider.CreateScope().ServiceProvider.GetScopedTwoService())
\u app.UseMiddleware(
app.ApplicationServices.GetWebSocketConnectionDictionary(),
serviceProvider.CreateScope().serviceProvider.GetScopedOneService(),
serviceProvider.CreateScope().serviceProvider.GetScopedTwoService())
我担心我每次在WebSocket请求上都会创建一个新的作用域,从那里我可以获得作用域服务(serviceOne,serviceTwo),并且在WebSocket连接关闭之前,它从未被释放。因为我只在websocket start上使用这些服务,并且在我开始收听即将发布的消息后,我从不使用它们(IScopedOneSerice,IScopedTwoService)

公共异步任务调用(HttpContext上下文,IServiceProvider服务)
{
wait_scopedOneService.MethodOne();
wait_scopedTwoService.MethodTwo();
//开始收听消息,如果我需要呼叫某个存储库
//我正在使用的方法
//IServiceProvider,即异构存储回购=
//service.GetRequiredService();//此repo也有作用域
}
这种方式是否可能导致内存泄漏

更新: 我试图实现的目标:让我们简单一点,每次我收到websocket消息时,我都需要将消息插入存储库,或者解析与其他业务逻辑服务通信的其他服务

public WebSocketManagerMiddleware(RequestDelegate next,
    IWebSocketConnectionDictionary webSocketDictionary,
    IServiceScopeFactory scopeFactory)
{
    _next = next;
    _webSocketManager = webSocketDictionary;
    _scopeFactory = scopeFactory;
}

我不确定向包含singleton websocket dictionary和一些其他作用域服务的websocket中间件中注入作用域服务的最佳方法是什么。

正如我在评论中所说,您应该注入一个
IServiceScopeFactory
,而不是作用域服务。然后,您可以使用它来解析作用域服务

public WebSocketManagerMiddleware(RequestDelegate next,
    IWebSocketConnectionDictionary webSocketDictionary,
    IServiceScopeFactory scopeFactory)
{
    _next = next;
    _webSocketManager = webSocketDictionary;
    _scopeFactory = scopeFactory;
}
然后,您可以创建一个新的作用域,并在需要访问它们时从那里解析服务

using (var scope = _scopeFactory.CreateScope())
{
    var scopedOneService = scope.ServiceProvider.GetRequiredService<IScopedServiceOne>();
    var scopedTwoService = scope.ServiceProvider.GetRequiredService<IScopedServiceTwo>();
    // do something with scoped services
}
使用(var scope=\u scopeFactory.CreateScope())
{
var scopedOneService=scope.ServiceProvider.GetRequiredService();
var scopedTwoService=scope.ServiceProvider.GetRequiredService();
//对作用域服务执行某些操作
}

您还应该阅读在本文中正确的内容,而不是在Chris的答案被发布的问题中正确的内容,这就是为什么它被否决的原因:)

正如我在评论中所说的,您应该插入一个
IServiceScopeFactory
,而不是范围服务。然后,您可以使用它来解析作用域服务

public WebSocketManagerMiddleware(RequestDelegate next,
    IWebSocketConnectionDictionary webSocketDictionary,
    IServiceScopeFactory scopeFactory)
{
    _next = next;
    _webSocketManager = webSocketDictionary;
    _scopeFactory = scopeFactory;
}
然后,您可以创建一个新的作用域,并在需要访问它们时从那里解析服务

using (var scope = _scopeFactory.CreateScope())
{
    var scopedOneService = scope.ServiceProvider.GetRequiredService<IScopedServiceOne>();
    var scopedTwoService = scope.ServiceProvider.GetRequiredService<IScopedServiceTwo>();
    // do something with scoped services
}
使用(var scope=\u scopeFactory.CreateScope())
{
var scopedOneService=scope.ServiceProvider.GetRequiredService();
var scopedTwoService=scope.ServiceProvider.GetRequiredService();
//对作用域服务执行某些操作
}

您还应该阅读在本文中哪个是正确的,而不是在Chris的答案被贴出的问题中,这就是为什么它被否决的原因:)

我认为您应该使用注入的
IServiceScopeFactory
解决中间件中的作用域服务,而不是试图从外部获取它们。将构造函数中的作用域服务替换为单个
IServiceScopeFactory
,并存储该服务。每次你必须使用一个作用域服务时,通过创建一个新的作用域并从那里解析它们来获取它们。我是否应该将作用域服务与using()一起使用,以便在使用后可以轻松地进行处置?你能否澄清你试图实现的目标(逐步流程)?好的,我将更新我的post1。WebSocket客户端连接到我的中间件。2.将新Websocket添加到字典。3.使用ScopedServiceOne、ScopedServiceWO验证WebSocket连接是否正确。4.如果它被验证了,那么我开始监听新消息5。一条新消息到达,我解析了某个作用域方法,该方法从消息中计算数据并插入到数据库6中。将响应发送到消息我认为您应该使用注入的
IServiceScopeFactory
解析中间件内部的作用域服务,而不是尝试从外部获取它们。将构造函数中的作用域服务替换为单个
IServiceScopeFactory
,并存储该服务。每次你必须使用一个作用域服务时,通过创建一个新的作用域并从那里解析它们来获取它们。我是否应该将作用域服务与using()一起使用,以便在使用后可以轻松地进行处置?你能否澄清你试图实现的目标(逐步流程)?好的,我将更新我的post1。WebSocket客户端连接到我的中间件。2.将新Websocket添加到字典。3.使用ScopedServiceOne、ScopedServiceWO验证WebSocket连接是否正确。4.如果它被验证了,那么我开始监听新消息5。一条新消息到达,我解析了某个作用域方法,该方法从消息中计算数据并插入到数据库6中。发送对消息“超时已过期”的响应。从池中获取连接之前经过的超时时间。发生这种情况的原因可能是所有池连接都在使用中,并且已达到最大池大小。“当WebSocket客户端每10毫秒发送一条消息时,我在执行负载测试时遇到此错误。”。每个到达的消息都会调用对我的数据库的INSERT查询。这是不是意味着我在什么地方漏水?负载测试开始5分钟后出现错误。从诊断工具中,我看到我的内存稳步增加,直到600mb,CPU使用率达到100%,这听起来不太好。我可以向您保证,仅使用
IServiceScopeFactory
中的作用域解析服务不会占用那么多CPU和内存。我假设你没有正确处理你的插座和连接。漏洞不在我给你看的代码中。您应该尝试调试ap