WPF+ASP.NET SignalR实现后台通知

  • WPF+ASP.NET SignalR实现后台通知已关闭评论
  • 16 次浏览
  • A+
所属分类:.NET技术
摘要

在实际业务中,当后台数据发生变化,客户端能够实时的收到通知,而不是由用户主动的进行页面刷新才能查看,这将是一个非常人性化的设计。比如数字化大屏,并没有人工的干预,而是自动的刷新数据,那如何才能实现数据的实时刷新呢?本文以一个简单示例,简述如何通过WPF+ASP.NET SignalR实现消息后台通知以及数据的实时刷新,仅供学习分享使用,如有不足之处,还请指正。

在实际业务中,当后台数据发生变化,客户端能够实时的收到通知,而不是由用户主动的进行页面刷新才能查看,这将是一个非常人性化的设计。比如数字化大屏,并没有人工的干预,而是自动的刷新数据,那如何才能实现数据的实时刷新呢?本文以一个简单示例,简述如何通过WPF+ASP.NET SignalR实现消息后台通知以及数据的实时刷新,仅供学习分享使用,如有不足之处,还请指正。

WPF+ASP.NET SignalR实现后台通知

 

 通过上一篇文章的学习,了解了如何通过SignalR实现在线聊天功能,在示例中,我们发现每一次的客户端连接都是一个新的实例对象,所以没有办法在中心对象中存储状态信息,所以为了存储用户列表,我们采用了静态变量的方式。并且在线聊天功能是用户发送一条消息(Chat),然后触发中心对象(ChatHub),转发给另一个用户(SendAsync)。那么如果实现数字化大屏,需要服务端持续的往客户端发送消息,而不是客户端主动触发,应该怎么做呢?这就是本文需要分享的内容。

涉及知识点

在本示例中,涉及知识点如下所示:

  1. 开发工具:Visual Studio 2022 目标框架:.NET6.0
  2. ASP.NET SignalR,一个ASP .NET 下的类库,可以在ASP .NET 的Web项目中实现实时通信,目前新版已支持.NET6.0及以上版本。在本示例中,作为消息通知的服务端。
  3. WPF,是微软推出的基于Windows 的用户界面框架,主要用于开发客户端程序。

前提条件

实现服务端持续往客户端发送消息,除了业务上的需求外,还需要满足两个条件:

  1. 在服务端有一个常驻内存对象,监听数据变化。
  2. 常驻内存对象,可以访问中心对象(ChatHub),能够获取中心对象的所有连接客户端,并发送消息。

满足以上两个条件,才可以实现想要的功能。

服务端

经过以上分析后,服务端分为两方面,核心对象(ChatHub),处理业务对象(Worker)。下面我们逐一说明:

ChatHub 中心是用于向连接到 SignalR 服务器的客户端发送消息的核心抽象,负责客户端的连接和断开。如下所示:

 1 using Microsoft.AspNetCore.SignalR;  2   3 namespace SignalRChat.Chat  4 {  5     public class ChatHub:Hub  6     {  7         public override Task OnConnectedAsync()  8         {  9             Console.WriteLine($"ID:{Context.ConnectionId} 已连接"); 10             return base.OnConnectedAsync(); 11         } 12  13         public override Task OnDisconnectedAsync(Exception? exception) 14         { 15             Console.WriteLine($"ID:{Context.ConnectionId} 已断开"); 16             return base.OnDisconnectedAsync(exception); 17         } 18     } 19 }

Worker实例为一个单例对象,常驻内容,实时监听数据变化,并通过ChatHub上下文(IHubContext<ChatHub>)获取连接信息,然后发送消息,如下所示:

 1 using Microsoft.AspNetCore.SignalR;  2   3 namespace SignalRChat.Chat  4 {  5     public class Worker  6     {  7         public static Worker Instance;  8           9         private static readonly object locker=new object(); 10  11         private IHubContext<ChatHub> context; 12  13         private System.Timers.Timer timer; 14  15         public Worker(IHubContext<ChatHub> context) {  16             this.context = context; 17             timer= new System.Timers.Timer(500);//单位毫秒 18             timer.Enabled=true; 19             timer.AutoReset=true;//自动重新 20             timer.Elapsed += Timer_Elapsed; 21             timer.Start(); 22         } 23  24         private void Timer_Elapsed(object? sender, System.Timers.ElapsedEventArgs e) 25         { 26             //模拟数据,一般情况下,从数据库获取,然后通知到客户端 27             Dictionary<string, object> data = new Dictionary<string, object>(); 28             var online = new Random().Next(0, 100); 29             var male = Math.Floor(new Random().NextSingle() * online); 30             var female = online - male; 31             data["online"]=online; 32             data["male"] =male; 33             data["female"] = female; 34             context.Clients.All.SendAsync("Data",data); 35         } 36  37         public static void Register(IHubContext<ChatHub> context) 38         { 39             if (Instance == null) 40             { 41                 lock (locker) 42                 { 43                     if (Instance == null) 44                     { 45                         Instance = new Worker(context); 46                     } 47                 } 48             } 49         } 50     } 51 }

注意:此处发送数据的是Data方法,客户端必须监听Data方法,才能接收数据。

如何创建单例对象呢,中心对象上下文不能自己创建,必须要和ChatHub通过注入方式的上下文是同一个,不然无法获取客户端连接信息。在项目启动时,通过中间件的方式创建,如下所示:

 1 using Microsoft.AspNetCore.SignalR;  2 using SignalRChat.Chat;  3   4 var builder = WebApplication.CreateBuilder(args);  5   6 // Add services to the container.  7   8 builder.Services.AddControllers();  9 // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle 10 builder.Services.AddEndpointsApiExplorer(); 11 builder.Services.AddSwaggerGen(); 12 //1.添加SignalR服务 13 builder.Services.AddSignalR(); 14 var app = builder.Build(); 15  16 // Configure the HTTP request pipeline. 17 if (app.Environment.IsDevelopment()) 18 { 19     app.UseSwagger(); 20     app.UseSwaggerUI(); 21 } 22 app.UseRouting(); 23 app.UseHttpsRedirection(); 24  25 app.UseAuthorization(); 26 //在Use中注册单例实例 27 app.Use(async (context, next) => 28 { 29     var hubContext = context.RequestServices 30                             .GetRequiredService<IHubContext<ChatHub>>(); 31     Worker.Register(hubContext);//调用静态方法注册 32  33     if (next != null) 34     { 35         await next.Invoke(); 36     } 37 }); 38 app.MapControllers(); 39 //2.映射路由 40 app.UseEndpoints(endpoints => { 41     endpoints.MapHub<ChatHub>("/chat"); 42 }); 43  44 app.Run();

客户端

客户端主要是连接服务器,然后监听服务端发送数据的方法即可,如下所示:

  1 namespace SignalRClient   2 {   3     public class ShowDataViewModel : ObservableObject   4     {   5         #region 属性及构造函数   6    7         private int online;   8    9         public int Online  10         {  11             get { return online; }  12             set { SetProperty(ref online, value); }  13         }  14   15         private int male;  16   17         public int Male  18         {  19             get { return male; }  20             set { SetProperty(ref male, value); }  21         }  22   23   24         private int female;  25   26         public int Female  27         {  28             get { return female; }  29             set { SetProperty(ref female, value); }  30         }  31   32         private HubConnection hubConnection;  33   34         public ShowDataViewModel()  35         {  36   37         }  38   39         #endregion  40   41         #region 命令  42   43         private ICommand loadedCommand;  44   45         public ICommand LoadedCommand  46         {  47             get  48             {  49                 if (loadedCommand == null)  50                 {  51                     loadedCommand = new RelayCommand<object>(Loaded);  52                 }  53                 return loadedCommand;  54             }  55         }  56   57         private void Loaded(object obj)  58         {  59             //1.初始化  60             InitInfo();  61             //2.监听  62             Listen();  63             //3.连接  64             Link();  65         }  66   67         #endregion  68   69         /// <summary>  70         /// 初始化Connection对象  71         /// </summary>  72         private void InitInfo()  73         {  74             hubConnection = new HubConnectionBuilder().WithUrl("https://localhost:7149/chat").WithAutomaticReconnect().Build();  75             hubConnection.KeepAliveInterval = TimeSpan.FromSeconds(5);  76         }  77   78         /// <summary>  79         /// 监听  80         /// </summary>  81         private void Listen()  82         {  83             hubConnection.On<Dictionary<string,object>>("Data", ReceiveInfos);  84         }  85   86         /// <summary>  87         /// 连接  88         /// </summary>  89         private async void Link()  90         {  91             try  92             {  93                 await hubConnection.StartAsync();  94             }  95             catch (Exception ex)  96             {  97                 MessageBox.Show(ex.Message);  98             }  99         } 100  101         private void ReceiveInfos(Dictionary<string, object> data) 102         { 103             if (data == null || data.Count < 1) 104             { 105                 return; 106             } 107             int.TryParse(data["online"]?.ToString(),out int online); 108             int.TryParse(data["male"]?.ToString(),out int male); 109             int.TryParse(data["female"]?.ToString(),out int female); 110             this.Online=online; 111             this.Male = male; 112             this.Female=female; 113         } 114     } 115 }

注意:监听Data方法,和服务端发送时保持一致。

运行示例

在示例中,需要同时启动服务端和客户端,所以以多项目方式启动,如下所示:

WPF+ASP.NET SignalR实现后台通知

 

 运行成功后,服务端以ASP.NET Web API的方式呈现,如下所示:

WPF+ASP.NET SignalR实现后台通知

 

 客户端运行如下:
WPF+ASP.NET SignalR实现后台通知

注意:客户端可以有多个,也可以是一个,后台通知消息,会通知到每一个连接的客户端。

源码下载

关注微信公众号,然后发送信息SignalR即可获取下载链接。如下所示:

WPF+ASP.NET SignalR实现后台通知

 

 

 

备注

以上就是WPF+ASP.NET SignalR实现后台实时通知的全部内容,关于SignalR的应用,实际场景有很多,这只是一个简单的入门示例,希望可以抛砖引玉,一起学习,共同进步。学习编程,从关注【老码识途】开始!!!