SignalR服务主动发送消息给客户端

news2024/11/26 13:51:50

文章目录

  • 背景
  • 尝试
  • 方案
    • 使用IHubContext上下文进行处理
    • 第一步 创建一个类用于处理上下文(WarningBroadcast)
    • 第二步:如何实例化这个对象呢
      • 下面是我实现的方式
    • 第三步:使用扩展类
  • 调用通知
  • 关于MessageBus的使用
    • demo
      • 发布消息
      • 订阅消息

背景

当服务端进行数据处理时(数据可能来源于非人工操作,比如各种控制器和信号源),需要将处理结果推送给客户端,进行实时数据显示。

尝试

在上一篇文章中我们创建过服务端,代码吗如下

using Microsoft.AspNetCore.SignalR;

namespace Demo_WarningMonitor.Api.SignalRHubs
{
    /// <summary>
    /// 报警广播
    /// </summary>
    public class WarningBroadcastHub : Hub
    { 
        private ILogger<WarningBroadcastHub> logger; 

        public WarningBroadcastHub(ILogger<WarningBroadcastHub> logger, IConfiguration configuration)
        {
            this.logger = logger; 
        }

        public async Task SendMessage(string user, string message)
        {
            try
            {
                await Clients.All.SendAsync("ReceiveMessage", user, message);
            }
            catch (Exception ex)
            {
                logger.LogError(ex,"发送消息出现异常");
            }
          
        }
    }
}

我想这直接在数据处理服务中i性能调用SendMessage方法就能实现发送消息了

但是事与愿违,因为这里涉及到一个对象声明周期的问题,在调用Clients.All的时候会提示调用了一个已经释放的资源对象,具体错误如下:System.ObjectDisposedException:"Cannot access a disposed object.

在这里插入图片描述

方案

使用IHubContext上下文进行处理

https://learn.microsoft.com/zh-cn/aspnet/core/signalr/hubcontext?view=aspnetcore-6.0

第一步 创建一个类用于处理上下文(WarningBroadcast)

我这里使用了MessageBus的一个中间件,这样就实现了解耦,Messagebus的nuget包

using Demo_WarningMonitor.Api.Models;
using iml6yu.MessageBus;
using iml6yu.MessageBus.Constand;
using Microsoft.AspNetCore.SignalR;

namespace Demo_WarningMonitor.Api.SignalRHubs
{
    public class WarningBroadcast
    {
        private ISubscriber<WarningMessage> warningSubscriber;
        private ISubscriber<string> realtimeDataSubscriber;
        private IConfiguration configuration;
        private string warningChannel;
        private ILogger<WarningBroadcast> logger;
        private IHubContext<WarningBroadcastHub> hubContext;//

        public WarningBroadcast(IConfiguration configuration, IHubContext<WarningBroadcastHub> context, ILogger<WarningBroadcast> logger)//<WarningBroadcastHub> 
        {
            hubContext = context;
            this.logger = logger;
            this.configuration = configuration;
            warningChannel = configuration.GetSection("WarningChannel").Get<string>();
            warningSubscriber = MessageBuses.Subscrib<WarningMessage>(warningChannel);
            warningSubscriber.OnNoticed += Subscriber_OnNoticed;

            realtimeDataSubscriber = MessageBuses.Subscrib<string>(configuration.GetSection("RealtimeDataChannel").Get<string>());
            realtimeDataSubscriber.OnNoticed += RealtimeDataSubscriber_OnNoticed;
        }

        private async void RealtimeDataSubscriber_OnNoticed(MessageChannel channel, MessageBusArges<string> message)
        {
            try
            {
                await hubContext.Clients.All.SendAsync("ReceiveMessage", "HubServiceCenter", message.Data);
            }
            catch (Exception ex)
            {
                logger.LogError(ex, "WarningBroadcast发送消息出现异常");
            }
        }

        /// <summary>
        /// 接收到消息的通知后进行分发处理
        /// </summary>
        /// <param name="channel"></param>
        /// <param name="message"></param>
        /// <exception cref="NotImplementedException"></exception>
        private async void Subscriber_OnNoticed(MessageChannel channel, MessageBusArges<WarningMessage> message)
        {
            try
            {
                Console.ForegroundColor = ConsoleColor.Red;

                var msg = System.Text.Json.JsonSerializer.Serialize(message.Data);
                await hubContext.Clients.All.SendAsync("WarningMessage", "HubServiceCenter", msg);

                Console.WriteLine("发送一次报警信息\r\n" + msg);

                Console.ForegroundColor = ConsoleColor.White;
            }
            catch (Exception ex)
            {
                logger.LogError(ex, "WarningBroadcast发送消息出现异常");
            }
        }
    }
}

这里的重点就是构造函数

第二步:如何实例化这个对象呢

这里涉及到如何获取IHubContext实例,可以查看文章

https://learn.microsoft.com/zh-cn/aspnet/core/signalr/hubcontext?view=aspnetcore-6.0

下面是我实现的方式

 var hubContext = app.Services.GetService<IHubContext<WarningBroadcastHub>>();
            if (hubContext != null)
            {
                new WarningBroadcast(app.Services.GetService<IConfiguration>(), hubContext,app.Services.GetService<ILogger<WarningBroadcast>>());
            }

对此我新建了一个扩展类,完整代码如下

using Microsoft.AspNetCore.SignalR;

namespace Demo_WarningMonitor.Api.SignalRHubs
{
    /// <summary>
    /// 扩展类
    /// </summary>
    public static class WarningBroadcastExt
    { 
        public static WebApplication UseWarningBroadcast(this WebApplication app)
        {
            var hubContext = app.Services.GetService<IHubContext<WarningBroadcastHub>>();
            if (hubContext != null)
            {
                new WarningBroadcast(app.Services.GetService<IConfiguration>(), hubContext,app.Services.GetService<ILogger<WarningBroadcast>>());
            }

            return app;
        }

    }
}

第三步:使用扩展类

在main函数中使用

  app.UseWarningBroadcast();

调用通知

在需要发送给客户端消息的时候使用

MessageBuses.Publish 推送一个消息,订阅者直接收到消息后就会调用await hubContext.Clients.All.SendAsync(“WarningMessage”, “HubServiceCenter”, msg); 给客户端发送消息了

关于MessageBus的使用

demo

发布消息

  MessageBuses.Publish<MyClass1>(new MyClass1());

订阅消息

   ISubscriber<MyClass1> subscriber;
   subscriber = MessageBuses.Subscrib<MyClass1>("newWin");
    subscriber.OnNoticed += (channel,e)=>{
       Debug.WriteLine(e.Data.ToString())  
    };

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/665577.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

java 心理教育网站系统Myeclipse开发mysql数据库web结构jsp编程计算机网页项目

一、源码特点 java 心理教育网站系统是一套完善的java web信息管理系统&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为TOMCAT7.0,Myeclipse8.5开发&#xff0c;数据库为Mysql5.0&…

使用 Flask 的g对象和 MySQL 实现用户登录和注销功能

在Flask中&#xff0c;g对象是一个特殊类型的对象&#xff0c;被称为"上下文全局变量"。它在一次请求的生命周期内存储信息&#xff0c;并且可以在整个请求过程中访问和共享。 g对象对于存储用户登录信息非常有用。例如&#xff0c;当用户通过验证登录时&#xff0c…

编译程序的任务

编译程序是一种翻译程序&#xff0c;编译程序是将一种语言形式翻译成另一种语言形式。它将高级语言所写的源程序翻译成等价的机器语言或汇编语言的目标程序。 整个编译过程一般可以划分为 5 个阶段&#xff1a;词法分析、语法分析、语义分析及中间代码生成、中间代码优化和目标…

UOS系统VMware安装教程

官网链接 https://home.uniontech.com/ 从这里下镜像文件 内存最好4以上 选择ISO文件地址 选择自定义安装 手动分区 4个g给交换分区&#xff0c;剩下的全挂在根目录下

长视频自动化摘要笔记完整工作流;腾讯云发布AIGC全链路内容安全解决方案

&#x1f989; AI新闻 &#x1f680; 腾讯云发布AIGC全链路内容安全解决方案&#xff0c;助力企业护航生成式人工智能健康发展 摘要&#xff1a;腾讯云公布MaaS能力全景图&#xff0c;提供AIGC全链路内容安全解决方案&#xff0c;覆盖从模型训练到内容生成再到事后运营全过程…

【工程应用八】终极的基于形状匹配方案解决(小模型+预生成模型+无效边缘去除+多尺度+各项异性+最小组件尺寸)

我估摸着这个应该是关于形状匹配或者模版匹配的最后一篇文章了&#xff0c;其实大概是2个多月前这些东西都已经弄完了&#xff0c;只是一直静不下来心整理文章&#xff0c;提醒一点&#xff0c;这篇文章后续可能会有多次修改&#xff08;但不会重新发文章&#xff0c;而是在后台…

搭建GPU环境的TensorFlow并将单块GPU划分逻辑为分区的实践

1、搭建环境 1.1、查看GPU版本 在安装tensorflow的GPU版本之前可以先看下自己的显卡情况 命令&#xff1a;nvidia-smi 或者桌面右下角&#xff0c;NVIDIA图标&#xff0c;进入到NVIDIA的控制面板&#xff1a; 点击左下角的系统信息&#xff0c;组件中查看NVCUDA64.dll的版本…

英特尔淡化混合 CPU-GPU 引擎,将 NNP 合并到 GPU 中

早在 2022 年 2 月&#xff0c;当英特尔宣布其“Falcon Shores”项目以构建混合 CPU-GPU 计算引擎时&#xff0c;该项目允许在单个插槽中独立扩展 CPU 和 GPU 容量&#xff0c;看起来这家芯片制造商正准备与竞争对手 Nvidia 较量AMD 开始使用混合计算电机&#xff0c;Intel 称之…

基于Flask框架和Vue框架搭建一个Web端的深度学习检测系统(从模型训练,界面设计到服务器部署实现一个完整项目实战)

从Pytorch框架下YOLOv5的模型训练&#xff0c;到Flask框架的模型加载&#xff0c;再到Vue框架的界面设计到最后的服务器部署。 实验环境 1.Windows10系统 2.编辑器pycharm 3.GPU 1080Ti 4.anaconda虚拟环境安装相应的安装包 5.pytorch版本1.7.1 6.Python3.7.15 实验数据集 …

C++初阶—stackqueue

目录 1. stack的介绍和使用 1.1 stack的介绍 1.2 stack使用及OJ 1.2.1 最小栈 1.2.2 栈的弹出压入顺序 1.2.3 逆波兰表达式求值 1.2.4 用两个栈实现一个队列 2. queue的介绍和使用 2.1 queue的介绍 2.2 queue的使用及OJ 2.2.1 用队列实现栈 2.3 queue的模拟实现 3…

用户测试:确保产品质量的关键一环

用户测试&#xff1a;确保产品质量的关键一环 在当今竞争激烈的市场中&#xff0c;产品的质量是企业脱颖而出的关键因素之一。为了确保产品的质量&#xff0c;用户测试成为了开发过程中不可或缺的一环。用户测试是通过让真实用户使用产品并提供反馈意见来验证产品的功能、易用性…

【系统开发】尚硅谷 - 谷粒商城项目笔记(四):JSR303数据校验

文章目录 JSR303数据校验引入依赖和简介配置验证规则开启验证BindResult校验的统一异常处理JSR303分组校验自定义校验注解 JSR303数据校验 引入依赖和简介 引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-bo…

Python和c语言爬虫如何选择?

Python是最受欢迎的爬虫语言之一&#xff0c;因为它易于学习和使用&#xff0c;有大量的库和框架可供选择。JavaScript通常用于Web爬虫&#xff0c;因为它可以直接在浏览器中运行&#xff0c;可以轻松地从动态网站中提取数据。java是一种广泛使用的语言&#xff0c;它有很多强大…

提高电商平台精准营销效果的IP定位离线库应用场景

随着电子商务的快速发展&#xff0c;越来越多的人们选择在线购物。随之而来的是消费者数量的增加和商品竞争的激烈。如何精准地找到目标客户&#xff0c;并进行有效的营销&#xff0c;成为了电商平台需要攻克的难题。在这种情况下&#xff0c;IP定位离线库技术的应用成为了电商…

Python基础语法第一章、认识Python

一、计算机基础概念 1.1什么是计算机? 很多老一辈的人, 管下面这个叫做计算机. 然鹅, 它只是 "计算器", 和计算机是有很大区别的. 现在我们所说的计算机, 不光能进行算术运算, 还能进行逻辑判断, 数据存储, 网络通信等等功能, 以至于可以自动的完成非常复杂的工作…

SerDes的原理解析

01 SerDes简介 首先我们要了解什么是SerDes&#xff0c;SerDes的应用场景又是什么呢&#xff1f;SerDes又有哪些常见的种类&#xff1f;做过FPGA的小伙伴想必都知道串口&#xff0c;与并行传输技术相比&#xff0c;串行传输技术的引脚数量少、扩展能力强、采 用点对点的连接方式…

从uCOSii中抠出来的内存管理程序

从uCOSii中抠出来的内存管理程序 1、学习uCOSii的内存管理的原因 操作系统和内存管理是分不开的&#xff0c;每个操作系统都有自己的一套内存管理方法。在实际应用中&#xff0c;我们尽量使用其自带的内存管理。学习和使用uCOSii也有一段时间了&#xff0c;觉得它的内存管理方…

高效处理报表,掌握原生JS打印和导出报表为PDF的顺畅技巧!

摘要&#xff1a;本文由葡萄城技术团队于CSDN原创并首发。转载请注明出处&#xff1a;葡萄城官网&#xff0c;葡萄城为开发者提供专业的开发工具、解决方案和服务&#xff0c;赋能开发者。 前言篇 在日常工作中&#xff0c;报表打印和导出为PDF是经常要处理的任务之一。除了方…

管理类联考——写作——素材篇——论说文——写作素材02——志篇:毅力·坚持

管理类专业学位联考 (写作能力) 论说文素材 02——志篇&#xff1a;毅力坚持 论文说材料: 骐骥一跃&#xff0c;不能十步&#xff1b;驽马十驾&#xff0c;功在不舍。 ——《荀子劝 学》 一&#xff1a;道理论据 咬住青山不放松&#xff0c;立根原在破岩中&#xff1b;千磨…

gitLens插件简单使用(默认上传github)

1.安装 在vscode中的插件管理输入如下后下载 GitLens — Git supercharged 2.配置 点击文件--首选项--设置 点击右上角设置小图标 3.github使用 首先仓库文件一定是要git init是git所管理的 1.在代码文件夹下使用git init创建仓库 2.打开vscode的git管理 3.点击添加暂存区…