创建项目

创建一个空的 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广播程序相关推荐

  1. 【SignalR学习系列】7. SignalR Hubs Api 详解(JavaScript 客户端)

    SignalR 的 generated proxy 服务端 public class ContosoChatHub : Hub {public void NewContosoChatMessage(s ...

  2. Spark Scala语言学习系列之完成HelloWorld程序(三种方式)

    三种方式完成HelloWorld程序 分别采用在REPL,命令行(scala脚本)和Eclipse下运行hello world. 一.Scala REPL. windows下安装好scala后,直接C ...

  3. 【Python学习系列四】Python程序通过hadoop-streaming提交到Hadoop集群执行MapReduce

    场景:将Python程序通过hadoop-streaming提交到Hadoop集群执行. 参考:http://www.michael-noll.com/tutorials/writing-an-had ...

  4. C# ASP.NET MVC 之 SignalR 学习 实时数据推送显示 配合 Echarts 推送实时图表

    本文主要是我在刚开始学习 SignalR 的技术总结,网上找的学习方法和例子大多只是翻译了官方给的一个例子,并没有给出其他一些经典情况的示例,所以才有了本文总结,我在实现推送简单的数据后,就想到了如何 ...

  5. Lichee_RV学习系列---认识Lichee Rv Dock、环境搭建和编译第一个程序

    Lichee Rv Dock学习系列文章目录 文章目录 Lichee Rv Dock学习系列文章目录 前言 一.认识Lichee RV 1.D1-H 芯片 2.Lichee RV开发板 3.系统镜像 ...

  6. ansible学习系列之顺利启动后台程序

    文章目录 ansible系列文章 场景 环境 原因 尝试 添加`nohup`指令 `source`环境变量 结果 总结 参考链接 随缘求赞 ansible系列文章 ansible学习系列之tags的使 ...

  7. [C# 网络编程系列]专题七:UDP编程补充——UDP广播程序的实现

    上次因为时间的关系,所以把上一个专题遗留下的一个问题在本专题中和大家分享下,本专题主要介绍下如何实现UDP广播的程序,下面就直接介绍实现过程和代码以及运行的结果. 一.程序实现 UDP广播程序的实现代 ...

  8. Android音视频学习系列(五) — 掌握音频基础知识并使用AudioTrack、OpenSL ES渲染PCM数据

    系列文章 Android音视频学习系列(一) - JNI从入门到精通 Android音视频学习系列(二) - 交叉编译动态库.静态库的入门 Android音视频学习系列(三) - Shell脚本入门 ...

  9. 数字电视业务PSI-SI学习系列

    目录 MPEG-2简介 TS流的生成与结构 DVB的分类 DVB SIPSI分析和处理 PATProgram Association Table节目关联表 PMTProgram Map Table节目 ...

最新文章

  1. GridView控件修改、删除示例(修改含有DropDownList控件)
  2. 二维“玄”如何“抖动”出三维世界?
  3. 536. Construct Binary Tree from String 从括号字符串中构建二叉树
  4. python读写xlsx文件_python读写Excel文件--使用xlrd模块读取,xlwt模块写入
  5. s7 200 java_java android 读写西门子PLC数据,包含S7协议和Fetch/Write协议,s7支持200smart,300PLC,1200PLC,1500PLC...
  6. asp.net core webApi 参数保护
  7. 父子沪c转大牌过户_机动车异地过户(转籍)
  8. 优秀的程序员VS糟糕的程序员
  9. Python 线程队列 LifoQueue – LIFO - Python零基础入门教程
  10. 【Elasticsearch】es keywods 类型数据 写入后查询不到
  11. SyntaxError: unexpected EOF while parsing成功解决
  12. 分享一款在线less转css的神器
  13. git add多个文件_10个节省时间和改善工作流的Git技巧
  14. jvm系列(五):tomcat性能调优和性能监控(visualvm)
  15. 【笔记总结】高中英语——其二:名词性从句
  16. Python 招聘信息爬取及可视化
  17. python高维数据空间的可视化?
  18. Problem B: 小度挑战赛
  19. Linux tar命令详解
  20. 【Python】不同目录下的.py文件调用问题

热门文章

  1. scala break continue
  2. ubuntu下安装nagios
  3. 雅虎公司C#笔试题,看看你能解答多少? [含答案]
  4. .NET 数据访问中间件 HyperDAL v1.1 FAQ
  5. C#递归获取JSON所有键值对
  6. Maven项目上总有一个小红叉问题
  7. Egret学习笔记 (Egret打飞机-3.实现背景循环滚动)
  8. taobao sass
  9. my SQL下载安装,环境配置,以及密码忘记的解决,以及navicat for mysql下载,安装,测试连接...
  10. How to add and configure jetty server in maven pom.xml