iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >WPF+ASP.NETSignalR实现动态折线图的绘制
  • 446
分享到

WPF+ASP.NETSignalR实现动态折线图的绘制

WPF动态折线图WPF折线图WPFSignalR折线图 2023-01-03 15:01:30 446人浏览 八月长安
摘要

目录什么是SignalRSignalR做了什么封装与集成SignalR用途官方网址和源码示例截图服务端项目创建SignalR服务端业务集成SignalR服务端配置客户端项目创建客户端

在实际业务中,当后台数据发生变化,客户端能够实时的收到通知,而不是由用户主动的进行页面刷新才能查看,这将是一个非常人性化的设计。有没有那么一种场景,后台数据明明已经发生变化了,前台却因为没有及时刷新,而导致页面显示的数据与实际存在差异,从而造成错误的判断。那么如何才能在后台数据变更时及时通知客户端呢?本文以一个简单的动态折线图示例,简述如何通过asp.net SignalR实现后台通知功能,仅供学习分享使用,如有不足之处,还请指正。

什么是SignalR

 ASP.net SignalR 是一个面向 ASP.NET 开发人员的库,可简化将实时 WEB 功能添加到应用程序的过程。 实时 web 功能是让服务器代码将内容推送到连接的客户端立即可用,而不是让服务器等待客户端请求新数据的能力。

SignalR做了什么

传统Http采用的是大家熟知的“拉模式”,即客户端发出的每次请求,服务端都是被动处理。此场景下客户端是老大,很显然只有一方主动,操作与处理起来就没那么完美。

为了能让服务端也能主动,HTML5的出现让这种变得可能,大家知道html5中有两种主动模式。第一种叫做websockect,websockets是Html5提供的新的api,可以在Web网页与服务器端间建立Socket连接,它是基于tcp模式的双工通讯。还有一种叫做SSE,也就是客户端来订阅服务器的一种事件模型。

在html5出来之前,如果要做到服务器主动,我们只能采用变相的longpool和iframe流勉强实现。

SignalR对上面四种方案进行了高度的封装,也就是说signalR会在这四种技术中根据浏览器和服务器设置采取最优的一种模式。

封装与集成

对于.NET开发者的福音,.NET平台为我们提供了一种简洁高效智能的实时信息交互技术->SignalR,它集成了上述数种技术,并能根据配置自动或手动选择其最佳应用。

SignalR用途

SignalR 提供了一个简单的 API,用于创建服务器到客户端远程过程调用 (rpc) ,该调用客户端浏览器 (和其他客户端平台中的 javascript 函数) 服务器端 .NET 代码。 SignalR 还包括用于连接管理的 API (,例如连接和断开连接事件) ,以及分组连接。

虽然聊天通常被用作示例,但你可以做更多的事情。每当用户刷新网页以查看新数据时,或者该网页实施 ajax 长轮询以检索新数据时,它都是使用 SignalR 的候选者。SignalR 还支持需要从服务器进行高频更新的全新类型的应用,例如实时游戏。

官方网址和源码

官方网址:https://dotnet.microsoft.com/zh-cn/apps/aspnet/signalr

微软API文档:https://learn.microsoft.com/zh-cn/aspnet/signalr/overview/getting-started/introduction-to-signalr

GitHub网址:https://github.com/SignalR

示例截图

本示例主要实现一个动态折线图功能,主要分为服务端和客户端两部分,示例如下所示:

服务端项目创建

1. 创建一个Web服务端程序(以ASP.NET webapi为例),默认情况下SignalR已经作为项目框架的一部分而存在,所以不需要安装,直接使用即可。通过项目--依赖性--框架--Microsoft.Aspnetcore.App可以查看

2. 创建ChatHub,继承Hub基类,作为后台连接管理的中心

using Microsoft.AspNetCore.SignalR;

namespace DemoSignalR.Server.Chat
{
    public class ChatHub : Hub
    {
        #region 连接和断开连接

        public override async Task OnConnectedAsync()
        {
            var connId = Context.ConnectionId;
            Console.WriteLine($"{connId} 已连接");
            await base.OnConnectedAsync();
        }

        public void StartNotify(string type)
        {
            if (type == "1")
            {

            }
            else if (type == "2")
            {

            };

        }

        public override async Task OnDisconnectedAsync(Exception ex)
        {
            //如果断开连接
            var connId = Context.ConnectionId;
            Console.WriteLine($"{connId} 已断开");
            await base.OnDisconnectedAsync(ex);
        }

        #endregion
    }
}

SignalR服务端业务集成

在实际业务中,存在各种需要后台通知的功能,根据不同的业务,可以采用不同的通知触发方式:

1. 在调用接口时触发后台通知

using DemoSignalR.Server.Chat;
using Microsoft.AspNetCore.mvc;
using Microsoft.AspNetCore.SignalR;

namespace DemoSignalR.Server.Controllers
{
    [ApiController]
    [Route("[controller]")]
    public class TestWebApiController : ControllerBase
    {


        private readonly ILogger<TestWebApiController> _logger;

        private IHubContext<ChatHub> _context;

        public TestWebApiController(ILogger<TestWebApiController> logger, IHubContext<ChatHub> context)
        {
            _logger = logger;
            _context = context;
        }

        [HttpGet]
        public void GetTestA(string Name)
        {
            string info = $"当前接收到的信息为:{Name},{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}";
            _context.Clients.All.SendAsync("", info);
        }


    }
}

2. 定时器循环通知

using Microsoft.AspNetCore.SignalR;
using System.Timers;

namespace DemoSignalR.Server.Chat
{
    public class TestChatInfo
    {
        private IHubContext<ChatHub> _context;

        private System.Timers.Timer _timer;

        private readonly static object locker = new object();//对象

        public static TestChatInfo instance;//当前实例

        private readonly ILogger _logger;

        private int _index = 0;

        private TestChatInfo(IHubContext<ChatHub> _context, ILogger _logger)
        {
            this._context = _context;
            this._logger = _logger;
            //定义定时器
            _timer = new System.Timers.Timer(100);
            _timer.AutoReset = true;
            _timer.Enabled = true;
            _timer.Elapsed += Timer_Elapsed;
            _timer.Start();
        }

        private void Timer_Elapsed(object? sender, ElapsedEventArgs e)
        {
            //业务逻辑判断
            var obj = new TestValue();
            obj.Index = this._index;
            obj.Value = DateTime.Now.Millisecond % 100;
            _context.Clients.All.SendAsync("RefreshInfos", obj);
            this._index++;
        }

        /// <summary>
        /// 注册,即初始化单例实例
        /// </summary>
        /// <param name="context"></param>
        /// <param name="reviewTaskService"></param>
        /// <param name="sysParamService"></param>
        public static void ReGISter(IHubContext<ChatHub> context, ILogger logger)
        {
            lock (locker)
            {
                if (instance == null)
                {
                    lock (locker)
                    {
                        instance = new TestChatInfo(context, logger);
                    }
                }
            }
        }

    }

    public class TestValue
    {
        private int index;
        public int Index { get { return index; } set { index = value; } }

        private float value;
        public float Value { get { return value; } set { this.value = value; } }
    }
}

SignalR服务端配置

 SignalR服务端配置主要分成三步:

1. 添加SignalR服务

2. 映射SignalR路由

3. 注册单例后台通知服务(如果其他方式,可省略)

using DemoSignalR.Server.Chat;
using Microsoft.AspNetCore.SignalR;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.

builder.Services.AddControllers();
// Learn more about configuring swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
//1.添加SignalR服务
builder.Services.AddSignalR();
builder.Services.AddLogging(logging => logging.AddConsole());

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}
app.UseRouting();
app.UseHttpsRedirection();

app.UseAuthorization();


//在Use中注册单例实例
app.Use(async (context, next) =>
{
    var hubContext = context.RequestServices.GetRequiredService<IHubContext<ChatHub>>();
    //var logger = context.RequestServices.GetRequiredService<ILogger>();
    TestChatInfo.Register(hubContext, null);//调用静态方法注册
    if (next != null)
    {
        await next.Invoke();
    }
});

app.MapControllers();

//2.映射路由
app.UseEndpoints(endpoints => {
    endpoints.MapHub<ChatHub>("/chat");
});

app.Run();

客户端项目创建

1. 创建WPF项目

2. 通过NuGet包管理器安装SignalR客户端

3. 创建SignalR状态管理,主要管理SignalR的连接,关闭,重连等操作。

using Microsoft.AspNetCore.SignalR.Client;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DemoSignalR.Client
{
    internal class SignalRClient
    {
        private readonly HubConnection hubConnection;

        public HubConnection HubConnection
        {
            get { return hubConnection; }
        }

        public SignalRClient()
        {
            var server = ConfigurationManager.AppSettings["Server"].ToString();
            hubConnection = new HubConnectionBuilder().WithUrl($"{server}/chat").WithAutomaticReconnect().Build();
            hubConnection.KeepAliveInterval = TimeSpan.FromSeconds(5);
        }

        public virtual void Listen()
        {

        }

        public async void Start()
        {
            try
            {
                await hubConnection.StartAsync();

            }
            catch (Exception e)
            {

            }
        }
    }
}

客户端业务逻辑处理

1. 根据不同的业务逻辑分别监听不同的通知事件。

2. 示例详见源码

using Microsoft.AspNetCore.SignalR.Client;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DemoSignalR.Client
{
    internal class TestSignalRClient : SignalRClient
    {
        public Action<object> RefreshInfos;

        public Action<string> Reconnected;

        public TestSignalRClient() : base()
        {
        }

        public override void Listen()
        {
            HubConnection.On<object>("RefreshInfos", (obj) =>
            {
                //
                if (obj != null)
                {
                    Console.WriteLine("收到数据");
                    //发送消息
                    if (RefreshInfos != null)
                    {
                        RefreshInfos(obj);
                    }
                }
            });
            HubConnection.Reconnected += HubConnection_Reconnected;
        }

        private Task HubConnection_Reconnected(string arg)
        {
            return Task.Run(() =>
            {
                if (Reconnected != null)
                {
                    Reconnected(arg);
                }
            });
        }

        public virtual void StartNotify(string condition)
        {
            HubConnection.SendAsync("StartNotify", condition);
            Console.WriteLine($"开始通过知{condition}");
        }
    }
}

SignalR需要注意事项

你不会实例化 Hub 类或从服务器上自己的代码调用其方法;由 SignalR Hubs 管道为你完成的所有操作。 SignalR 每次需要处理中心操作(例如客户端连接、断开连接或向服务器发出方法调用时)时,SignalR 都会创建 Hub 类的新实例。

由于 Hub 类的实例是暂时性的,因此无法使用它们来维护从一个方法调用到下一个方法的状态。 每当服务器从客户端收到方法调用时,中心类的新实例都会处理消息。 若要通过多个连接和方法调用来维护状态,请使用一些其他方法(例如数据库)或 Hub 类上的静态变量,或者不派生自 Hub的其他类。 如果在内存中保留数据,请使用 Hub 类上的静态变量等方法,则应用域回收时数据将丢失。

如果要从在 Hub 类外部运行的代码将消息发送到客户端,则无法通过实例化 Hub 类实例来执行此操作,但可以通过获取对 Hub 类的 SignalR 上下文对象的引用来执行此操作。

注意:ChatHub每次调用都是一个新的实例,所以不可以有私有属性或变量,不可以保存对像的值,所以如果需要记录一些持久保存的值,则可以采用静态变量,或者中心以外的对象。

关于源码

本示例中相关源码,已上传至gitee(码云),链接如下:https://gitee.com/ahsiang/demo-signal-r

以上就是WPF+ASP.NET SignalR实现动态折线图的绘制的详细内容,更多关于WPF绘制动态折线图的资料请关注编程网其它相关文章!

--结束END--

本文标题: WPF+ASP.NETSignalR实现动态折线图的绘制

本文链接: https://www.lsjlt.com/news/176527.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • WPF+ASP.NETSignalR实现动态折线图的绘制
    目录什么是SignalRSignalR做了什么封装与集成SignalR用途官方网址和源码示例截图服务端项目创建SignalR服务端业务集成SignalR服务端配置客户端项目创建客户端...
    99+
    2023-01-03
    WPF 动态折线图 WPF 折线图 WPF SignalR 折线图
  • Vue+Echarts实现绘制动态折线图
    目录1 引入Echarts1.1 安装1.2 引入1.3 基本使用2 动态折线图2.1 基本折线图2.2 动态折线图补充1 引入Echarts 1.1 安装 使用如下命令通过 npm...
    99+
    2023-03-19
    Vue Echarts绘制动态折线图 Vue Echarts绘制折线图 Vue Echarts 折线图 Vue Echarts
  • 怎么使用Vue+Echarts实现绘制动态折线图
    今天小编给大家分享一下怎么使用Vue+Echarts实现绘制动态折线图的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。1 引入...
    99+
    2023-07-05
  • QtQChart实现折线图的绘制
    目录前言1.使用2.效果如下3.具体实现如下4.刷新QChart5.PCL 点排序前言 QChart  是常用的图表;我这里做了一个 default 和 custom 1....
    99+
    2023-05-17
    Qt QChart绘制折线图 Qt QChart折线图 Qt QChart
  • Python matplotlib实现折线图的绘制
    目录一、版本二、图表主题设置三、一次函数四、多个一次函数五、填充折线图官网: https://matplotlib.org 一、版本 # 01 matplotlib安装情况 imp...
    99+
    2024-04-02
  • python多线程实现动态图绘制
    目录一、背景二、步骤1、使用matplotlib绘制动态图2、创建一个线程用于更新数据三、代码框架一、背景 有些情况下,我们面对实时更新的数据,希望能够在一个窗口中可视化出来,并且能...
    99+
    2024-04-02
  • Android实现绘制折线图APP代码
    目录一.总体设计二.具体模块实现三.效果展示四.功能展望总结一.总体设计 1.寻找规律,公式化的生成坐标系。 2.将生成坐标系的关键参数设置为可自定义,从而可变的可以生成自己想要的坐...
    99+
    2024-04-02
  • Python+Matplotlib实现绘制三维折线图
    目录1.0简介2.0三维图画法与类型1、直线绘制(Line plots)2、散点绘制(Scatter plots)3、线框图(Wireframe plots)4、三角表面图(Tri-...
    99+
    2023-03-21
    Python Matplotlib绘制三维折线图 Python Matplotlib 三维折线图 Python Matplotlib
  • WPF+WriteableBitmap实现高性能曲线图的绘制
    目录一、前言二、正文三、运行效果一、前言 之前分享过一期关于DrawingVisual来绘制高性能曲线的博客,今天再分享一篇通过另一种方式来绘制高性能曲线的方法,也就是通过Write...
    99+
    2022-11-13
    WPF WriteableBitmap绘制曲线图 WPF WriteableBitmap 曲线图 WPF WriteableBitmap
  • 基于Echart实现折线图的绘制详解
    效果图 不显示折线图上的拐点方法 ,3个都可以使用,代码中有显示在什么位置使用。 symbolSize:0, symbol:“none”, showSymb...
    99+
    2024-04-02
  • python多线程怎么实现动态图绘制
    今天小编给大家分享一下python多线程怎么实现动态图绘制的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。一、背景有些情况下,...
    99+
    2023-06-30
  • Android实现动态曲线绘制
    我们在安卓开发中,有时会用到统计图表的功能,而曲线绘制是其中比较典型的一种,一般是利用给定的坐标点集和安卓自带的绘图模块进行绘制,直接得到的是一张完整的静态的曲线图。但有时,我们需要...
    99+
    2024-04-02
  • D3.js实现绘制折线图的教程详解
    目录x轴比例尺数据折线d3.lined3.area水平方向垂直方向总结本章我们来实现一下折线图,有了画柱状图的经验,我们可以快速的分析出柱状图和折线图的区别主要是x轴比例尺和绘制数据...
    99+
    2022-11-13
    D3.js绘制折线图 D3.js 折线图
  • 如何用html5代码实现绘制折线图
    这期内容当中小编将会给大家带来有关如何用html5代码实现绘制折线图,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。XML/HTML Code复制内容到剪贴板<htm...
    99+
    2024-04-02
  • WPF仿LiveCharts实现饼图的绘制
    目录前言 一、PieControl.cs二、App.xaml三、MainWindow.xaml四、MainWindow.xaml.cs每日一笑 下班和实习生一起回家,公交站...
    99+
    2024-04-02
  • Android绘制双折线图的方法
    本文实例为大家分享了Android绘制双折线图的具体代码,供大家参考,具体内容如下 自定义View实现双折线图,可点击,点击后带标签描述,暂未实现拖动的功能,实现效果如下: 代码如...
    99+
    2024-04-02
  • Python实现动态柱状图的绘制
    目录一.基础柱状图二.基础时间线柱状图三.GDP动态柱状图绘制四.完整代码一.基础柱状图 如图 演示 from pyecharts.charts import Bar from p...
    99+
    2022-12-29
    Python绘制动态柱状图 Python动态柱状图 Python 柱状图
  • android绘制曲线和折线图的方法
    本文实例为大家分享了android绘制曲线和折线图的具体代码,供大家参考,具体内容如下 (曲线)  (折线) 1.CurveView.java package com....
    99+
    2024-04-02
  • WPF如何实现绘制3D图形
    今天小编给大家分享一下WPF如何实现绘制3D图形的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。关键概念视口视口指的是图像要展...
    99+
    2023-07-05
  • Android怎么实现动态曲线绘制
    这篇文章主要介绍了Android怎么实现动态曲线绘制的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Android怎么实现动态曲线绘制文章都会有所收获,下面我们一起来看看吧。我们在安卓开发中,有时会用到统计图表的...
    99+
    2023-07-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作