亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

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

2019-11-17 01:25:59
字體:
來源:轉載
供稿:網友

[渣譯文] 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包來安裝一個簡單的模擬股票行情應用。在本教程的第一部分,您將從頭開始創建一個應用程序的簡化版本。在本教程的剩余部分,您將安裝NuGet包,審閱Sample中的一些附加功能。

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

第一步,您將要創建該應用程序的顯示表格用于顯示數據。

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

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

創建項目

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

2.選擇空項目并確定。

編寫服務器代碼

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

創建Stock類

首先我們來創建一個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及價格之間的差額并輸出結果。

創建StockTicker及StockTickerHub類

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

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

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

 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 }

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

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

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

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

  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類必須是線程安全的。

在靜態字段中存儲單例

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

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
久久亚洲影音av资源网| 亚洲成人国产精品| 亚洲激情在线观看视频免费| 国产精品99久久久久久人| 青青草成人在线| 成人疯狂猛交xxx| 欧美日韩免费区域视频在线观看| 亚洲综合中文字幕68页| 欧美成人激情在线| 亚洲欧美自拍一区| 亚洲欧美日韩中文在线| 欧美激情一区二区三区在线视频观看| 俺去啦;欧美日韩| 国产精品a久久久久久| 国内精品久久久久| 欧美视频免费在线观看| 97在线观看免费| 夜夜嗨av色一区二区不卡| 欧美亚洲第一区| 欧美电影院免费观看| 中文字幕免费精品一区| 国内成人精品一区| 欧美国产乱视频| 久热99视频在线观看| 国产又爽又黄的激情精品视频| 91国在线精品国内播放| 蜜臀久久99精品久久久久久宅男| 亚洲精品电影网| 亚洲成人在线视频播放| 一区二区三区高清国产| 欧美日韩一区二区在线播放| 亚洲精品理论电影| 日韩av网址在线| 性欧美激情精品| 亚洲精品欧美日韩| 日韩av手机在线观看| 亚洲精品免费一区二区三区| 97婷婷涩涩精品一区| www.亚洲男人天堂| 在线看国产精品| 精品国产老师黑色丝袜高跟鞋| 国产精品福利久久久| 一区二区三区视频在线| 国产91免费看片| 91美女高潮出水| 欧美日韩激情小视频| 大桥未久av一区二区三区| 亚洲激情免费观看| 亚洲在线免费观看| 日本一区二区三区四区视频| 午夜免费久久久久| 在线日韩第一页| 欧美日韩人人澡狠狠躁视频| 欧美一级电影久久| 神马久久桃色视频| 成人a在线视频| 中文字幕亚洲国产| 久久精品国产99国产精品澳门| 国产精品99久久久久久白浆小说| 国产亚洲人成网站在线观看| 中文字幕一区日韩电影| 日韩电视剧在线观看免费网站| 91九色国产视频| 91久久精品一区| 视频在线观看一区二区| 久久久久免费精品国产| 日韩亚洲精品视频| 2019中文字幕在线观看| 日本高清久久天堂| 亚洲女成人图区| 日韩精品免费观看| 欧美成人亚洲成人| 免费av在线一区| 亚洲国产成人精品女人久久久| 欧美xxxx14xxxxx性爽| 国产欧美在线观看| 日韩欧美第一页| 国产日韩欧美另类| 日韩精品在线播放| 57pao国产精品一区| 久久99国产精品自在自在app| 国产日韩欧美91| 亚洲欧美制服综合另类| 国产视频999| 欧美在线免费观看| 在线观看日韩视频| 亚洲高清一二三区| 国产精品久久久久久久av大片| 91高清视频免费| 日本欧美一二三区| 国内精品模特av私拍在线观看| 日韩经典一区二区三区| 日韩中文字幕精品| 国产69精品99久久久久久宅男| 久久97精品久久久久久久不卡| 亚洲xxx视频| 国产精品综合网站| 亚洲欧美成人网| 久久五月天色综合| 国产精品扒开腿做爽爽爽的视频| 亚洲一区二区三区乱码aⅴ| 亚洲精品二三区| 国产精品久久久久秋霞鲁丝| 性金发美女69hd大尺寸| 亚洲日韩中文字幕在线播放| 久久影视电视剧凤归四时歌| 国产精品高清在线观看| 欧美亚洲视频在线观看| 亚洲aⅴ男人的天堂在线观看| 高清欧美性猛交xxxx| 91精品国产九九九久久久亚洲| 在线播放国产一区二区三区| 国自在线精品视频| 欧美性猛交xxxx免费看漫画| 色综合久久天天综线观看| 国产在线a不卡| 亚洲精品成人免费| 欧美国产日韩xxxxx| 影音先锋欧美在线资源| 久久视频国产精品免费视频在线| 亚洲电影免费观看高清完整版在线观看| 亚洲精品97久久| 欧美一区视频在线| 欧美日韩免费区域视频在线观看| 成人精品视频99在线观看免费| 91精品国产91久久久久久久久| 欧美成人午夜免费视在线看片| 国产精品三级在线| 亚洲成人国产精品| 欧美性猛交xxxx免费看久久久| 日韩精品在线免费播放| 日本中文字幕成人| 国产999视频| 国产91露脸中文字幕在线| 国产精品入口日韩视频大尺度| 久久国产视频网站| 最近中文字幕2019免费| 亚洲人a成www在线影院| 国外日韩电影在线观看| 欧美午夜久久久| 一区二区日韩精品| 欧美国产精品va在线观看| 孩xxxx性bbbb欧美| 国产精品久久久久久av下载红粉| 色婷婷综合久久久久中文字幕1| 国产成人亚洲综合91精品| 91av成人在线| 久久久久久久久久久人体| 亚洲男人天堂视频| 精品视频一区在线视频| 日韩精品在线观看视频| 久久久999国产精品| 高清欧美性猛交xxxx黑人猛交| 疯狂蹂躏欧美一区二区精品| 亚洲午夜国产成人av电影男同| 九九热精品视频国产| 久久久人成影片一区二区三区| 亚洲自拍中文字幕| 成人网中文字幕| 亚洲国模精品私拍| 欧美孕妇性xx| 国产精品18久久久久久麻辣| 日韩中文字幕久久| 尤物精品国产第一福利三区|