• 利用SignalR实施响应股票数据波动


    1.新建ASP.NET Web应用程序,  选择Empty模板。

    2.创建Stock.cs类

     1  public class Stock
     2     {
     3         /// <summary>
     4         /// 价格
     5         /// </summary>
     6         private decimal _price;
     7 
     8         /// <summary>
     9         /// 象征
    10         /// </summary>
    11         public string Symbol { get; set; }
    12 
    13         public decimal Price
    14         {
    15             get
    16             {
    17                 return _price;
    18             }
    19             set
    20             {
    21                 if (_price == value)
    22                 {
    23                     return;
    24                 }
    25 
    26                 _price = value;
    27 
    28                 if (DayOpen == 0)
    29                 {
    30                     DayOpen = _price;
    31                 }
    32             }
    33         }
    34         /// <summary>
    35         /// 开放
    36         /// </summary>
    37         public decimal DayOpen { get; private set; }
    38 
    39        /// <summary>
    40        /// 变动
    41        /// </summary>
    42         public decimal Change
    43         {
    44             get
    45             {
    46                 return Price - DayOpen;
    47             }
    48         }
    49 
    50         /// <summary>
    51         /// 变动百分比
    52         /// </summary>
    53         public double PercentChange
    54         {
    55             get
    56             {
    57                 return (double)Math.Round(Change / Price, 4);
    58             }
    59         }
    60     }
    Stock.cs

    3.选择程序包管理控制台,添加SignalR Nuget包

    输入命令 install-package Microsoft.AspNet.SignalR

    4.选择添加SignalR Hub Class(v2),命名StockTickerHub

    5.StockTickerHub.cs类

     1  [HubName("stockTickerMini")]
     2     public class StockTickerHub : Hub
     3     {
     4    private readonly StockTicker _stockTicker;
     5 
     6         public StockTickerHub() : this(StockTicker.Instance) { }
     7 
     8         public StockTickerHub(StockTicker stockTicker)
     9         {
    10             _stockTicker = stockTicker;
    11         }
    12 
    13         public IEnumerable<Stock> GetAllStocks()
    14         {
    15             return _stockTicker.GetAllStocks();
    16         }
    17     }
    StockTickerHub.cs

    6.添加StockTicker.cs类

     1   public class StockTicker
     2     {
     3         // 单例线程
     4         private readonly static Lazy<StockTicker> _instance = new Lazy<StockTicker>(() => new StockTicker(GlobalHost.ConnectionManager.GetHubContext<StockTickerHub>().Clients));
     5         private readonly ConcurrentDictionary<string, Stock> _stocks = new ConcurrentDictionary<string, Stock>();
     6         private readonly object _updateStockPricesLock = new object();
     7         private readonly double _rangePercent = .002;
     8         private readonly TimeSpan _updateInterval = TimeSpan.FromMilliseconds(250);
     9         private readonly Random _updateOrNotRandom = new Random();
    10         private readonly Timer _timer;
    11         //_updatingStockPrices标志被标记为volatile以确保对其进行线程安全访问。
    12         private volatile bool _updatingStockPrices = false;
    13 
    14         private StockTicker(IHubConnectionContext<dynamic> clients)
    15         {
    16 
    17             //构造函数使用一些示例股票数据初始化_stocks集合,
    18             //GetAllStocks返回股票。
    19             //这些股票集合又由StockTickerHub.GetAllStocks返回,
    20             //这是客户可以调用的Hub类中的服务器方法。
    21             Clients = clients;
    22             _stocks.Clear();
    23             var stocks = new List<Stock>
    24             {
    25                 new Stock { Symbol = "MSFT", Price = 30.31m },
    26                 new Stock { Symbol = "APPL", Price = 578.18m },
    27                 new Stock { Symbol = "GOOG", Price = 570.30m }
    28             };
    29             stocks.ForEach(stock => _stocks.TryAdd(stock.Symbol, stock));
    30 
    31             //构造函数启动一个Timer对象,
    32             //该对象定期调用随机更新股票价格的方法。
    33             _timer = new Timer(UpdateStockPrices, null, _updateInterval, _updateInterval);
    34 
    35         }
    36 
    37         public static StockTicker Instance
    38         {
    39             get
    40             {
    41                 return _instance.Value;
    42             }
    43         }
    44 
    45         private IHubConnectionContext<dynamic> Clients
    46         {
    47             get;
    48             set;
    49         }
    50 
    51         public IEnumerable<Stock> GetAllStocks()
    52         {
    53             return _stocks.Values;
    54         }
    55         private void UpdateStockPrices(object state)
    56         {
    57             lock (_updateStockPricesLock)
    58             {
    59                 if (!_updatingStockPrices)
    60                 {
    61                     _updatingStockPrices = true;
    62 
    63                     foreach (var stock in _stocks.Values)
    64                     {
    65                         if (TryUpdateStockPrice(stock))
    66                         {
    67                             BroadcastStockPrice(stock);
    68                         }
    69                     }
    70 
    71                     _updatingStockPrices = false;
    72                 }
    73             }
    74         }
    75         private bool TryUpdateStockPrice(Stock stock)
    76         {
    77             // Randomly choose whether to update this stock or not
    78             var r = _updateOrNotRandom.NextDouble();
    79             if (r > .1)
    80             {
    81                 return false;
    82             }
    83 
    84             // Update the stock price by a random factor of the range percent
    85             var random = new Random((int)Math.Floor(stock.Price));
    86             var percentChange = random.NextDouble() * _rangePercent;
    87             var pos = random.NextDouble() > .51;
    88             var change = Math.Round(stock.Price * (decimal)percentChange, 2);
    89             change = pos ? change : -change;
    90 
    91             stock.Price += change;
    92             return true;
    93         }
    94 
    95         private void BroadcastStockPrice(Stock stock)
    96         {
    97             Clients.All.updateStockPrice(stock);
    98         }
    99     }
    StockTicker.cs

    7.添加Startup.cs类

    1  public class Startup
    2     {
    3         public void Configuration(IAppBuilder app)
    4         {
    5             app.MapSignalR();
    6         }
    7     }
    Startup.cs

    8.设置前端代码

     1 <!DOCTYPE html>
     2 <html xmlns="http://www.w3.org/1999/xhtml">
     3 <head>
     4     <title>ASP.NET SignalR Stock Ticker</title>
     5     <style>
     6         body {
     7             font-family: 'Segoe UI', Arial, Helvetica, sans-serif;
     8             font-size: 16px;
     9         }
    10 
    11         #stockTable table {
    12             border-collapse: collapse;
    13         }
    14 
    15             #stockTable table th, #stockTable table td {
    16                 padding: 2px 6px;
    17             }
    18 
    19             #stockTable table td {
    20                 text-align: right;
    21             }
    22 
    23         #stockTable .loading td {
    24             text-align: left;
    25         }
    26 
    27         #stockTicker {
    28             overflow: hidden;
    29              450px;
    30             height: 24px;
    31             border: 1px solid #999;
    32         }
    33 
    34             #stockTicker .inner {
    35                  9999px;
    36             }
    37 
    38             #stockTicker ul {
    39                 display: inline-block;
    40                 list-style-type: none;
    41                 margin: 0;
    42                 padding: 0;
    43             }
    44 
    45             #stockTicker li {
    46                 display: inline-block;
    47                 margin-right: 8px;
    48             }
    49 
    50             /*<li data-symbol="{Symbol}"><span class="symbol">{Symbol}</span><span class="price">{Price}</span><span class="change">{PercentChange}</span></li>*/
    51             #stockTicker .symbol {
    52                 font-weight: bold;
    53             }
    54 
    55             #stockTicker .change {
    56                 font-style: italic;
    57             }
    58     </style>
    59 </head>
    60 <body>
    61     <h1>ASP.NET SignalR Stock Ticker Sample</h1>
    62 
    63     <h2>Live Stock Table</h2>
    64     <div id="stockTable">
    65         <table border="1">
    66             <thead>
    67                 <tr><th>Symbol</th><th>Price</th><th>Open</th><th>Change</th><th>%</th></tr>
    68             </thead>
    69             <tbody>
    70                 <tr class="loading"><td colspan="5">loading...</td></tr>
    71             </tbody>
    72         </table>
    73     </div>
    74 
    75     <!--Script references. -->
    76     <!--Reference the jQuery library. -->
    77     <script src="/Scripts/jquery-1.10.2.min.js"></script>
    78     <!--Reference the SignalR library. -->
    79     <script src="/Scripts/jquery.signalR-2.1.2.js"></script>
    80     <!--Reference the autogenerated SignalR hub script. -->
    81     <script src="/signalr/hubs"></script>
    82     <!--Reference the StockTicker script. -->
    83     <script src="StockTicker.js"></script>
    84 </body>
    85 </html>
    html

    9.创建StockTicker.js

     1 // A simple templating method for replacing placeholders enclosed in curly braces.
     2 if (!String.prototype.supplant) {
     3     String.prototype.supplant = function (o) {
     4         return this.replace(/{([^{}]*)}/g,
     5             function (a, b) {
     6                 var r = o[b];
     7                 return typeof r === 'string' || typeof r === 'number' ? r : a;
     8             }
     9         );
    10     };
    11 }
    12 
    13 $(function () {
    14 
    15     var ticker = $.connection.stockTickerMini, // the generated client-side hub proxy
    16         up = '',
    17         down = '',
    18         $stockTable = $('#stockTable'),
    19         $stockTableBody = $stockTable.find('tbody'),
    20         rowTemplate = '<tr data-symbol="{Symbol}"><td>{Symbol}</td><td>{Price}</td><td>{DayOpen}</td><td>{Direction} {Change}</td><td>{PercentChange}</td></tr>';
    21 
    22     function formatStock(stock) {
    23         return $.extend(stock, {
    24             Price: stock.Price.toFixed(2),
    25             PercentChange: (stock.PercentChange * 100).toFixed(2) + '%',
    26             Direction: stock.Change === 0 ? '' : stock.Change >= 0 ? up : down
    27         });
    28     }
    29 
    30     function init() {
    31         ticker.server.getAllStocks().done(function (stocks) {
    32             $stockTableBody.empty();
    33             $.each(stocks, function () {
    34                 var stock = formatStock(this);
    35                 $stockTableBody.append(rowTemplate.supplant(stock));
    36             });
    37         });
    38     }
    39 
    40     function scrollTicker() {
    41         var w = $stockTickerUl.width();
    42         $stockTickerUl.css({ marginLeft: w });
    43         $stockTickerUl.animate({ marginLeft: -w }, 15000, 'linear', scrollTicker);
    44     }
    45     // Add a client-side hub method that the server will call
    46     ticker.client.updateStockPrice = function (stock) {
    47         var displayStock = formatStock(stock),
    48             $row = $(rowTemplate.supplant(displayStock));
    49 
    50         $stockTableBody.find('tr[data-symbol=' + stock.Symbol + ']')
    51             .replaceWith($row);
    52     }
    53 
    54     // Start the connection
    55     $.connection.hub.start().done(init);
    56 
    57 });
    StockTicker.js

    10.最终效果

    具体可看微软官方:

     https://docs.microsoft.com/en-us/aspnet/signalr/overview/getting-started/tutorial-server-broadcast-with-signalr

    好好学习,天天向上。
  • 相关阅读:
    Leetcode 1184. 公交站间的距离
    Leetcode 1232. 缀点成线
    Leetcode1539. 第 k 个缺失的正整数
    Leetcode 1299. 将每个元素替换为右侧最大元素
    Leetcode 1508. 子数组和排序后的区间和
    Leetcode 1509. 三次操作后最大值与最小值的最小差
    Leetcode 1207. 独一无二的出现次数
    Leetcode 1507. 转变日期格式
    Leetcode 1217. 玩筹码
    SQL Server自动产生一年多少周及月
  • 原文地址:https://www.cnblogs.com/Zhengxue/p/9025332.html
Copyright © 2020-2023  润新知