【SignalR学习系列】4. SignalR广播程序
创建项目
创建一个空的 Web 项目,并在 Nuget 里面添加 SignalR,jQuery UI 包,添加以后项目里包含了 jQuery,jQuery.UI ,和 SignalR 的脚本。
服务端代码
创建 Stock 类
using System;namespace SignalRDemo4 {public class Stock{private decimal _price;public string Symbol { get; set; }public decimal Price{get{return _price;}set{if (_price == value){return;}_price = value;if (DayOpen == 0){DayOpen = _price;}}}public decimal DayOpen { get; private set; }public decimal Change{get{return Price - DayOpen;}}public double PercentChange{get{return (double)Math.Round(Change / Price, 4);}}} }
创建 tockTicker 和 StockTickerHub 类
添加类 StockTicker
using Microsoft.AspNet.SignalR; using Microsoft.AspNet.SignalR.Hubs; using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Threading; using System.Web;namespace SignalRDemo4 {public class StockTicker{// Singleton instanceprivate readonly static Lazy<StockTicker> _instance = new Lazy<StockTicker>(() => new StockTicker(GlobalHost.ConnectionManager.GetHubContext<StockTickerHub>().Clients));private readonly ConcurrentDictionary<string, Stock> _stocks = new ConcurrentDictionary<string, Stock>();private readonly object _updateStockPricesLock = new object();//stock can go up or down by a percentage of this factor on each changeprivate readonly double _rangePercent = .002;private readonly TimeSpan _updateInterval = TimeSpan.FromMilliseconds(250);private readonly Random _updateOrNotRandom = new Random();private readonly Timer _timer;private volatile bool _updatingStockPrices = false;private StockTicker(IHubConnectionContext<dynamic> clients){Clients = clients;_stocks.Clear();var stocks = new List<Stock>{new Stock { Symbol = "MSFT", Price = 30.31m },new Stock { Symbol = "APPL", Price = 578.18m },new Stock { Symbol = "GOOG", Price = 570.30m }};stocks.ForEach(stock => _stocks.TryAdd(stock.Symbol, stock));_timer = new Timer(UpdateStockPrices, null, _updateInterval, _updateInterval);}public static StockTicker Instance{get{return _instance.Value;}}private IHubConnectionContext<dynamic> Clients{get;set;}public IEnumerable<Stock> GetAllStocks(){return _stocks.Values;}private void UpdateStockPrices(object state){lock (_updateStockPricesLock){if (!_updatingStockPrices){_updatingStockPrices = true;foreach (var stock in _stocks.Values){if (TryUpdateStockPrice(stock)){BroadcastStockPrice(stock);}}_updatingStockPrices = false;}}}private bool TryUpdateStockPrice(Stock stock){// Randomly choose whether to update this stock or notvar r = _updateOrNotRandom.NextDouble();if (r > .1){return false;}// Update the stock price by a random factor of the range percentvar random = new Random((int)Math.Floor(stock.Price));var percentChange = random.NextDouble() * _rangePercent;var pos = random.NextDouble() > .51;var change = Math.Round(stock.Price * (decimal)percentChange, 2);change = pos ? change : -change;stock.Price += change;return true;}private void BroadcastStockPrice(Stock stock){Clients.All.updateStockPrice(stock);}} }
为了线程安全,把 Stock 的数据存储在了 ConcurrentDictionary 里面。
添加 SignalR Hub Class
using System; using System.Collections.Generic; using System.Linq; using System.Web; using Microsoft.AspNet.SignalR; using Microsoft.AspNet.SignalR.Hubs;namespace SignalRDemo4 {[HubName("stockTickerMini")]public class StockTickerHub : Hub{private readonly StockTicker _stockTicker;public StockTickerHub() : this(StockTicker.Instance) { }public StockTickerHub(StockTicker stockTicker){_stockTicker = stockTicker;}public IEnumerable<Stock> GetAllStocks(){return _stockTicker.GetAllStocks();}} }
添加 Owin 类,并在里面配置 SignalR
using System; using System.Threading.Tasks; using Microsoft.Owin; using Owin;[assembly: OwinStartup(typeof(SignalRDemo4.Startup))]namespace SignalRDemo4 {public class Startup{public void Configuration(IAppBuilder app){// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=316888 app.MapSignalR();}} }
客户端代码
添加名为 StockTicker 的html页面,设置为启动页面,并替换为下面代码。
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head><title>ASP.NET SignalR Stock Ticker</title><style>body {font-family: 'Segoe UI', Arial, Helvetica, sans-serif;font-size: 16px;}#stockTable table {border-collapse: collapse;}#stockTable table th, #stockTable table td {padding: 2px 6px;}#stockTable table td {text-align: right;}#stockTable .loading td {text-align: left;}</style> </head> <body><h1>ASP.NET SignalR Stock Ticker Sample</h1><h2>Live Stock Table</h2><div id="stockTable"><table border="1"><thead><tr><th>Symbol</th><th>Price</th><th>Open</th><th>Change</th><th>%</th></tr></thead><tbody><tr class="loading"><td colspan="5">loading...</td></tr></tbody></table></div><!--Script references. --><!--Reference the jQuery library. --><script src="Scripts/jquery-3.1.1.min.js"></script><!--Reference the SignalR library. --><script src="Scripts/jquery.signalR-2.2.2.js"></script><!--Reference the autogenerated SignalR hub script. --><script src="/signalr/hubs"></script><!--Reference the StockTicker script. --><script src="Scripts/StockTicker.js"></script> </body> </html>
添加名为 StockTicker 的js文件,并添加下面代码
// A simple templating method for replacing placeholders enclosed in curly braces. if (!String.prototype.supplant) {String.prototype.supplant = function (o) {return this.replace(/{([^{}]*)}/g,function (a, b) {var r = o[b];return typeof r === 'string' || typeof r === 'number' ? r : a;});}; }$(function () {var ticker = $.connection.stockTickerMini, // the generated client-side hub proxyup = '▲',down = '▼',$stockTable = $('#stockTable'),$stockTableBody = $stockTable.find('tbody'),rowTemplate = '<tr data-symbol="{Symbol}"><td>{Symbol}</td><td>{Price}</td><td>{DayOpen}</td><td>{Direction} {Change}</td><td>{PercentChange}</td></tr>';function formatStock(stock) {return $.extend(stock, {Price: stock.Price.toFixed(2),PercentChange: (stock.PercentChange * 100).toFixed(2) + '%',Direction: stock.Change === 0 ? '' : stock.Change >= 0 ? up : down});}function init() {ticker.server.getAllStocks().done(function (stocks) {$stockTableBody.empty();$.each(stocks, function () {var stock = formatStock(this);$stockTableBody.append(rowTemplate.supplant(stock));});});}// Add a client-side hub method that the server will callticker.client.updateStockPrice = function (stock) {var displayStock = formatStock(stock),$row = $(rowTemplate.supplant(displayStock));$stockTableBody.find('tr[data-symbol=' + stock.Symbol + ']').replaceWith($row);}// Start the connection $.connection.hub.start().done(init);});
然后按F5进行调试,打开多个浏览器,发现里面的数据会同步更新。
源代码链接:
链接: https://pan.baidu.com/s/1pKRIR2r 密码: em9k
参考链接:
https://docs.microsoft.com/zh-cn/aspnet/signalr/overview/getting-started/tutorial-server-broadcast-with-signalr
转载于:https://www.cnblogs.com/Soulless/p/7224442.html
【SignalR学习系列】4. SignalR广播程序相关推荐
- 【SignalR学习系列】7. SignalR Hubs Api 详解(JavaScript 客户端)
SignalR 的 generated proxy 服务端 public class ContosoChatHub : Hub {public void NewContosoChatMessage(s ...
- Spark Scala语言学习系列之完成HelloWorld程序(三种方式)
三种方式完成HelloWorld程序 分别采用在REPL,命令行(scala脚本)和Eclipse下运行hello world. 一.Scala REPL. windows下安装好scala后,直接C ...
- 【Python学习系列四】Python程序通过hadoop-streaming提交到Hadoop集群执行MapReduce
场景:将Python程序通过hadoop-streaming提交到Hadoop集群执行. 参考:http://www.michael-noll.com/tutorials/writing-an-had ...
- C# ASP.NET MVC 之 SignalR 学习 实时数据推送显示 配合 Echarts 推送实时图表
本文主要是我在刚开始学习 SignalR 的技术总结,网上找的学习方法和例子大多只是翻译了官方给的一个例子,并没有给出其他一些经典情况的示例,所以才有了本文总结,我在实现推送简单的数据后,就想到了如何 ...
- Lichee_RV学习系列---认识Lichee Rv Dock、环境搭建和编译第一个程序
Lichee Rv Dock学习系列文章目录 文章目录 Lichee Rv Dock学习系列文章目录 前言 一.认识Lichee RV 1.D1-H 芯片 2.Lichee RV开发板 3.系统镜像 ...
- ansible学习系列之顺利启动后台程序
文章目录 ansible系列文章 场景 环境 原因 尝试 添加`nohup`指令 `source`环境变量 结果 总结 参考链接 随缘求赞 ansible系列文章 ansible学习系列之tags的使 ...
- [C# 网络编程系列]专题七:UDP编程补充——UDP广播程序的实现
上次因为时间的关系,所以把上一个专题遗留下的一个问题在本专题中和大家分享下,本专题主要介绍下如何实现UDP广播的程序,下面就直接介绍实现过程和代码以及运行的结果. 一.程序实现 UDP广播程序的实现代 ...
- Android音视频学习系列(五) — 掌握音频基础知识并使用AudioTrack、OpenSL ES渲染PCM数据
系列文章 Android音视频学习系列(一) - JNI从入门到精通 Android音视频学习系列(二) - 交叉编译动态库.静态库的入门 Android音视频学习系列(三) - Shell脚本入门 ...
- 数字电视业务PSI-SI学习系列
目录 MPEG-2简介 TS流的生成与结构 DVB的分类 DVB SIPSI分析和处理 PATProgram Association Table节目关联表 PMTProgram Map Table节目 ...
最新文章
- GridView控件修改、删除示例(修改含有DropDownList控件)
- 二维“玄”如何“抖动”出三维世界?
- 536. Construct Binary Tree from String 从括号字符串中构建二叉树
- python读写xlsx文件_python读写Excel文件--使用xlrd模块读取,xlwt模块写入
- s7 200 java_java android 读写西门子PLC数据,包含S7协议和Fetch/Write协议,s7支持200smart,300PLC,1200PLC,1500PLC...
- asp.net core webApi 参数保护
- 父子沪c转大牌过户_机动车异地过户(转籍)
- 优秀的程序员VS糟糕的程序员
- Python 线程队列 LifoQueue – LIFO - Python零基础入门教程
- 【Elasticsearch】es keywods 类型数据 写入后查询不到
- SyntaxError: unexpected EOF while parsing成功解决
- 分享一款在线less转css的神器
- git add多个文件_10个节省时间和改善工作流的Git技巧
- jvm系列(五):tomcat性能调优和性能监控(visualvm)
- 【笔记总结】高中英语——其二:名词性从句
- Python 招聘信息爬取及可视化
- python高维数据空间的可视化?
- Problem B: 小度挑战赛
- Linux tar命令详解
- 【Python】不同目录下的.py文件调用问题
热门文章
- scala break continue
- ubuntu下安装nagios
- 雅虎公司C#笔试题,看看你能解答多少? [含答案]
- .NET 数据访问中间件 HyperDAL v1.1 FAQ
- C#递归获取JSON所有键值对
- Maven项目上总有一个小红叉问题
- Egret学习笔记 (Egret打飞机-3.实现背景循环滚动)
- taobao sass
- my SQL下载安装,环境配置,以及密码忘记的解决,以及navicat for mysql下载,安装,测试连接...
- How to add and configure jetty server in maven pom.xml