国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發(fā)設計 > 正文

[渣譯文] SignalR 2.0 系列:SignalR的服務器廣播

2019-11-17 01:25:59
字體:
來源:轉載
供稿:網(wǎng)友

[渣譯文] SignalR 2.0 系列:SignalR的服務器廣播

2014-03-13 09:18 by Bce, ... 閱讀, ... 評論, 收藏, 編輯

英文渣水平,大伙湊合著看吧……

這是微軟官方SignalR 2.0教程Getting Started with asp.net SignalR 2.0系列的翻譯,這里是第八篇:SignalR的服務器廣播

原文:Tutorial: Server Broadcast with SignalR 2.0

概述

VS可以通過 Microsoft.AspNet.SignalR.SampleNuGet包來安裝一個簡單的模擬股票行情應用。在本教程的第一部分,您將從頭開始創(chuàng)建一個應用程序的簡化版本。在本教程的剩余部分,您將安裝NuGet包,審閱Sample中的一些附加功能。

本模擬股票行情應用代表了實時應用中的"推",或稱之為廣播,即我們將消息通知傳播給所有已連接客戶端。

第一步,您將要創(chuàng)建該應用程序的顯示表格用于顯示數(shù)據(jù)。

接下來,服務器會隨機更新股票價格,并且將新數(shù)據(jù)推送至所有連接的客戶端以更新表格。在瀏覽器中的表格上,價格及百分比列中的數(shù)字都會隨著服務器推送數(shù)據(jù)而自動更新。如果你打開更多的瀏覽器,它們都會顯示相同的數(shù)據(jù)及自動更新。

注意:如果您你不想自己手動來構建這一應用程序,你可以再一個新的空ASP.NET WEB應用項目中安裝Simple包,通過閱讀這些步驟來獲取代碼的解釋。本教程的第一部分涵蓋了Sample的子集,第二部分解釋了包中的一些附加功能。

創(chuàng)建項目

1.新建一個新的ASP.NET應用程序,命名為SignalR.StockTicker并創(chuàng)建。

2.選擇空項目并確定。

編寫服務器代碼

在本節(jié)中,我們來編寫服務器端代碼。

創(chuàng)建Stock類

首先我們來創(chuàng)建一個Stock模型類,用來存儲和傳輸股票信息。

1.新建一個類,命名為Stock.cs,然后輸入以下代碼:

 1 using System; 2  3 namespace SignalR.StockTicker 4 { 5     public class Stock 6     { 7         PRivate decimal _price; 8  9         public string Symbol { get; set; }10 11         public decimal Price12         {13             get14             {15                 return _price;16             }17             set18             {19                 if (_price == value)20                 {21                     return;22                 }23 24                 _price = value;25 26                 if (DayOpen == 0)27                 {28                     DayOpen = _price;29                 }30             }31         }32 33         public decimal DayOpen { get; private set; }34 35         public decimal Change36         {37             get38             {39                 return Price - DayOpen;40             }41         }42 43         public double PercentChange44         {45             get46             {47                 return (double)Math.Round(Change / Price, 4);48             }49         }50     }51 }

您設置了兩個屬性:股票代碼及價格。其他的屬性則依賴于你如何及何時設置股票價格。當您首次設定價格時,價格將被存儲在DayOpen中。之后隨著股票價格的改變,Change和PercentChange會自動計算DayOpen及價格之間的差額并輸出結果。

創(chuàng)建StockTicker及StockTickerHub類

您將使用SignalR集線器類的API來處理服務器到客戶端的交互。StockTickerHub衍生自SignalR集線器基類,用來處理接收客戶端的連接和調(diào)用方法。你還需要維護存儲的數(shù)據(jù),建立一個獨立于客戶端連接的Timer對象,來觸發(fā)價格更新。你不能將這些功能放在集線器中,因為每個針對集線器的操作,比如從客戶端到服務器端的連接與調(diào)用都會建立一個集線器的新實例,每個集線器的實例生存期是短暫的。因此,保存數(shù)據(jù),價格,廣播等更新機制需要放在一個單獨的類中。在此項目中我們將其命名為StockTicker。

你只需要一個StockTicker類的實例。所以你需要使用設計模式中的單例模式,從每個StockTickerHub的類中添加對StockTicker單一實例的引用。由于StockTicker類包含股票數(shù)據(jù)并觸發(fā)更新,所以它必須能夠廣播到每個客戶端。但StockTicker本身并不是一個集線器類,所以StockTicker類必須得到一個SignalR集線器連接上下文對象的引用,之后就可以使用這個上下文對象來將數(shù)據(jù)廣播給客戶端。

1.添加一個新的SignalR集線器類,命名為StockTickerHub并使用以下的代碼替換其內(nèi)容:

 1 using System.Collections.Generic; 2 using Microsoft.AspNet.SignalR; 3 using Microsoft.AspNet.SignalR.Hubs; 4  5 namespace SignalR.StockTicker 6 { 7     [HubName("stockTickerMini")] 8     public class StockTickerHub : Hub 9     {10         private readonly StockTicker _stockTicker;11 12         public StockTickerHub() : this(StockTicker.Instance) { }13 14         public StockTickerHub(StockTicker stockTicker)15         {16             _stockTicker = stockTicker;17         }18 19         public IEnumerable<Stock> GetAllStocks()20         {21             return _stockTicker.GetAllStocks();22         }23     }24 }

此集線器類用來定義用于客戶端調(diào)用的服務器方法。我們定義了一個GetAllStocks方法,當一個客戶端首次連接至服務器時,它會調(diào)用此方法來獲取所有股票的清單及當期價格。該方法可以同步執(zhí)行并返回IEnumerable<Sotck>,因為這些數(shù)據(jù)是從內(nèi)存中返回的。如果該方法需要做一些涉及等待的額外處理任務,比如數(shù)據(jù)庫查詢或調(diào)用Web服務來獲取數(shù)據(jù),您將指定Task<IEnumerable<Stock>>作為返回值已啟用異步處理。關于異步處理的更多信息,請參閱:ASP.NET SignalR Hubs API Guide - Server - When to execute asynchronously。

HubName特性定義了客戶端的JS代碼使用何種名稱來調(diào)用集線器。如果你不使用這個特性,默認將通過采用使用Camel規(guī)范的類名來調(diào)用。在本例中,我們使用stockTickerHun。

稍后我們將創(chuàng)建StockTicker類,如您所見,我們在這里使用了單例模式。使用一個靜態(tài)實例屬性來創(chuàng)建這個類的單一實例。StockTicker的單例將一直保留在內(nèi)存中,不管有多少客戶端連接或斷開連接。并且使用該實例中包含的GetAllStocks方法返回股票信息。

2.添加一個新類,命名為StockTicker.cs,并使用以下代碼替換內(nèi)容:

  1 using System;  2 using System.Collections.Concurrent;  3 using System.Collections.Generic;  4 using System.Threading;  5 using Microsoft.AspNet.SignalR;  6 using Microsoft.AspNet.SignalR.Hubs;  7   8   9 namespace SignalR.StockTicker 10 { 11     public class StockTicker 12     { 13         // Singleton instance 14         private readonly static Lazy<StockTicker> _instance = new Lazy<StockTicker>(() => new StockTicker(GlobalHost.ConnectionManager.GetHubContext<StockTickerHub>().Clients)); 15  16         private readonly ConcurrentDictionary<string, Stock> _stocks = new ConcurrentDictionary<string, Stock>(); 17  18         private readonly object _updateStockPricesLock = new object(); 19  20         //stock can go up or down by a percentage of this factor on each change 21         private readonly double _rangePercent = .002; 22  23         private readonly TimeSpan _updateInterval = TimeSpan.FromMilliseconds(250); 24         private readonly Random _updateOrNotRandom = new Random(); 25  26         private readonly Timer _timer; 27         private volatile bool _updatingStockPrices = false; 28  29         private StockTicker(IHubConnectionContext clients) 30         { 31             Clients = clients; 32  33             _stocks.Clear(); 34             var stocks = new List<Stock> 35             { 36                 new Stock { Symbol = "MSFT", Price = 30.31m }, 37                 new Stock { Symbol = "APPL", Price = 578.18m }, 38                 new Stock { Symbol = "GOOG", Price = 570.30m } 39             }; 40             stocks.ForEach(stock => _stocks.TryAdd(stock.Symbol, stock)); 41  42             _timer = new Timer(UpdateStockPrices, null, _updateInterval, _updateInterval); 43  44         } 45  46         public static StockTicker Instance 47         { 48             get 49             { 50                 return _instance.Value; 51             } 52         } 53  54         private IHubConnectionContext Clients 55         { 56             get; 57             set; 58         } 59  60         public IEnumerable<Stock> GetAllStocks() 61         { 62             return _stocks.Values; 63         } 64  65         private void UpdateStockPrices(object state) 66         { 67             lock (_updateStockPricesLock) 68             { 69                 if (!_updatingStockPrices) 70                 { 71                     _updatingStockPrices = true; 72  73                     foreach (var stock in _stocks.Values) 74                     { 75                         if (TryUpdateStockPrice(stock)) 76                         { 77                             BroadcastStockPrice(stock); 78                         } 79                     } 80  81                     _updatingStockPrices = false; 82                 } 83             } 84         } 85  86         private bool TryUpdateStockPrice(Stock stock) 87         { 88             // Randomly choose whether to update this stock or not 89             var r = _updateOrNotRandom.NextDouble(); 90             if (r > .1) 91             { 92                 return false; 93             } 94  95             // Update the stock price by a random factor of the range percent 96             var random = new Random((int)Math.Floor(stock.Price)); 97             var percentChange = random.NextDouble() * _rangePercent; 98             var pos = random.NextDouble() > .51; 99             var change = Math.Round(stock.Price * (decimal)percentChange, 2);100             change = pos ? change : -change;101 102             stock.Price += change;103             return true;104         }105 106         private void BroadcastStockPrice(Stock stock)107         {108             Clients.All.updateStockPrice(stock);109         }110 111     }112 }

由于運行時會有多個線程對StockTicker的同一個實例進行操作,StockTicker類必須是線程安全的。

在靜態(tài)字段中存儲單例

下面的代碼用于在靜態(tài)_instance字段中初始化一個StockTicker的實例。這是該類的唯一一個實例,因為構造函數(shù)已經(jīng)被標記為私有的。_instance中的延遲初

發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 微博| 大田县| 梅州市| 米易县| 探索| 喀喇沁旗| 嫩江县| 乌恰县| 贵德县| 苍山县| 陇川县| 江阴市| 大竹县| 垣曲县| 射阳县| 开江县| 博爱县| 乐昌市| 厦门市| 龙海市| 阳原县| 孝感市| 陈巴尔虎旗| 武宣县| 饶河县| 鹤山市| 中江县| 通海县| 霸州市| 岳西县| 蓬莱市| 黔西| 日土县| 玉树县| 南川市| 宣汉县| 嘉义县| 偃师市| 紫阳县| 昌黎县| 闽侯县|