チュートリアル: ASP.NET SignalR 1.x によるサーバー ブロードキャストTutorial: Server Broadcast with ASP.NET SignalR 1.x

によってPatrick FletcherTom Dykstraby Patrick Fletcher, Tom Dykstra

Warning

このドキュメントは SignalR の最新バージョンはありません。This documentation isn't for the latest version of SignalR. 見てASP.NET Core SignalRします。Take a look at ASP.NET Core SignalR.

このチュートリアルでは、ASP.NET SignalR を使用してサーバー ブロードキャストの機能を提供する web アプリケーションを作成する方法を示します。This tutorial shows how to create a web application that uses ASP.NET SignalR to provide server broadcast functionality. サーバー ブロードキャストでは、クライアントに送信される通信が、サーバーによって開始されたことを意味します。Server broadcast means that communications sent to clients are initiated by the server. このシナリオでは、チャット アプリケーションをクライアントに送信される通信が 1 つまたは複数のクライアントによって開始されたなどのピア ツー ピア シナリオよりもさまざまなプログラミングのアプローチが必要です。This scenario requires a different programming approach than peer-to-peer scenarios such as chat applications, in which communications sent to clients are initiated by one or more of the clients.

このチュートリアルで作成するアプリケーションでは、株価情報、サーバー ブロードキャストの機能の一般的なシナリオをシミュレートします。The application that you'll create in this tutorial simulates a stock ticker, a typical scenario for server broadcast functionality.

このチュートリアルでコメントは、ようこそ。Comments on the tutorial are welcome. チュートリアルに直接関係のない質問がある場合は、ASP.NET SignalR フォーラムまたはStackOverflow.comにて投稿してください。If you have questions that are not directly related to the tutorial, you can post them to the ASP.NET SignalR forum or StackOverflow.com.

概要Overview

Microsoft.AspNet.SignalR.Sample NuGet パッケージは、Visual Studio プロジェクトにサンプルのシミュレートされた株価表示器アプリケーションをインストールします。The Microsoft.AspNet.SignalR.Sample NuGet package installs a sample simulated stock ticker application in a Visual Studio project. このチュートリアルの最初の部分では、最初からそのアプリケーションの簡略化されたバージョンを作成します。In the first part of this tutorial, you'll create a simplified version of that application from scratch. チュートリアルの残りの部分では、NuGet パッケージをインストールし、作成したコードの追加の機能を確認します。In the remainder of the tutorial, you'll install the NuGet package and review the additional features and code that it creates.

株価表示器アプリケーションは、ある種のリアルタイムをしアプリケーション「プッシュ」またはブロードキャストの通知を定期的に接続されているすべてのクライアントをサーバーからの代表者です。The stock ticker application is a representative of a kind of real-time application in which you want to periodically "push," or broadcast, notifications from the server to all connected clients.

このチュートリアルの最初の部分でビルドするアプリケーションでは、株価データを持つグリッドが表示されます。The application that you'll build in the first part of this tutorial displays a grid with stock data.

StockTicker 初期バージョン

定期的に、サーバーはランダムに株価を更新し、更新プログラムをすべて接続されているクライアントにプッシュします。Periodically the server randomly updates stock prices and pushes the updates to all connected clients. ブラウザー、数字、およびシンボルで、 変更% 通知をサーバーからの応答で列を動的に変更します。In the browser the numbers and symbols in the Change and % columns dynamically change in response to notifications from the server. 同じ URL に他のブラウザーを開いた場合、同じデータやデータに同じ変更を同時にすべて表示します。If you open additional browsers to the same URL, they all show the same data and the same changes to the data simultaneously.

このチュートリアルには、次のセクションが含まれています。This tutorial contains the following sections:

Note

新しい SignalR.Sample パッケージをインストールするには、アプリケーションの構築の手順を実行しない場合は、空の ASP.NET Web アプリケーションプロジェクト、およびコードの説明を取得する次の手順を通読します。If you don't want to work through the steps of building the application, you can install the SignalR.Sample package in a new Empty ASP.NET Web Application project, and read through these steps to get explanations of the code. このチュートリアルの最初の部分が、SignalR.Sample コードのサブセットについて説明し、2 番目の部分が SignalR.Sample パッケージの追加機能の主な機能を説明します。The first part of the tutorial covers a subset of the SignalR.Sample code, and the second part explains key features of the additional functionality in the SignalR.Sample package.

必須コンポーネントPrerequisites

開始する前にある Visual Studio 2012 または 2010 SP1 がコンピューターにインストールされていることを確認します。Before you start, make sure that you have Visual Studio 2012 or 2010 SP1 installed on your computer. Visual Studio を持っていない場合は、次を参照してください。 ASP.NET ダウンロード、無料の Visual Studio 2012 Express for Web を取得します。If you don't have Visual Studio, see ASP.NET Downloads to get the free Visual Studio 2012 Express for Web.

Visual Studio 2010 があれば、以下のことを確認NuGetがインストールされています。If you have Visual Studio 2010, make sure that NuGet is installed.

プロジェクトの作成Create the project

  1. ファイルボタンをクリックし新しいプロジェクトします。From the File menu click New Project.

  2. 新しいプロジェクト] ダイアログ ボックスで、展開c# [テンプレート選択とWebします。In the New Project dialog box, expand C# under Templates and select Web.

  3. 選択、空の ASP.NET Web アプリケーション名では、プロジェクト テンプレートは、 SignalR.StockTicker、 をクリックOKします。Select the ASP.NET Empty Web Application template, name the project SignalR.StockTicker, and click OK.

    [新しいプロジェクト] ダイアログ ボックス

SignalR の NuGet パッケージを追加します。Add the SignalR NuGet Packages

SignalR と JQuery の NuGet パッケージを追加します。Add the SignalR and JQuery NuGet Packages

プロジェクトに SignalR の機能を追加するには、NuGet パッケージをインストールします。You can add SignalR functionality to a project by installing a NuGet package.

  1. クリックしてツール |NuGet パッケージ マネージャー |パッケージ マネージャー コンソールします。Click Tools | NuGet Package Manager | Package Manager Console.

  2. パッケージ マネージャーで、次のコマンドを入力します。Enter the following command in the package manager.

    Install-Package Microsoft.AspNet.SignalR -Version 1.1.3
    

    SignalR パッケージは、依存関係として、多くの他の NuGet パッケージをインストールします。The SignalR package installs a number of other NuGet packages as dependencies. インストールが完了するとすべての ASP.NET アプリケーションで SignalR を使用するために必要なサーバーとクライアント コンポーネントがあります。When the installation is finished you have all of the server and client components required to use SignalR in an ASP.NET application.

サーバー コードを設定します。Set up the server code

このセクションでは、サーバーで実行されるコードを設定します。In this section you set up the code that runs on the server.

在庫クラスを作成します。Create the Stock class

まず、格納および転送については、在庫を使用する在庫のモデル クラスを作成します。You begin by creating the Stock model class that you'll use to store and transmit information about a stock.

  1. プロジェクト フォルダーに新しいクラス ファイルを作成、名前を付けますStock.cs、テンプレート コードを次のコードに置き換えます。Create a new class file in the project folder, name it Stock.cs, and then replace the template code with the following code:

    using System;
    
    namespace SignalR.StockTicker
    {
        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);
                }
            }
        }
    }
    

    素材を作成するときに設定する 2 つのプロパティは、(たとえば、Microsoft の MSFT) シンボルと価格は。The two properties that you'll set when you create stocks are the Symbol (for example, MSFT for Microsoft) and the Price. その他のプロパティは、価格を設定する方法とタイミングに依存します。The other properties depend on how and when you set Price. 初めての価格を設定する値は、DayOpen に反映を取得します。The first time you set Price, the value gets propagated to DayOpen. 価格、変更を設定していて PercentChange プロパティの値を計算以降の時間は、価格と DayOpen の違いに基づきます。Subsequent times when you set Price, the Change and PercentChange property values are calculated based on the difference between Price and DayOpen.

StockTicker と StockTickerHub クラスを作成します。Create the StockTicker and StockTickerHub classes

サーバーからクライアントへの対話を処理するために、SignalR Hub API を使用します。You'll use the SignalR Hub API to handle server-to-client interaction. SignalR ハブ クラスから派生した StockTickerHub クラスでは、クライアントからの受信接続とメソッドの呼び出しを処理します。A StockTickerHub class that derives from the SignalR Hub class will handle receiving connections and method calls from clients. 株価データを維持し、クライアント接続とは無関係に、価格の更新プログラムを定期的にトリガーするタイマー オブジェクトを実行する必要があります。You also need to maintain stock data and run a Timer object to periodically trigger price updates, independently of client connections. ハブ インスタンスは一時的なので、ハブ クラスでこれらの関数を配置することはできません。You can't put these functions in a Hub class, because Hub instances are transient. 接続と、クライアントからサーバーへの呼び出しなど、ハブの各操作ではハブ クラスのインスタンスが作成されます。A Hub class instance is created for each operation on the hub, such as connections and calls from the client to the server. 株価データを保持し、価格を更新、価格の更新プログラムにブロードキャスト メカニズム StockTicker 名前を付けます別のクラスで実行するようにします。So the mechanism that keeps stock data, updates prices, and broadcasts the price updates has to run in a separate class, which you'll name StockTicker.

StockTicker からブロードキャスト

各 StockTickerHub インスタンスから、シングルトン StockTicker インスタンスへの参照を設定する必要がありますので、サーバー上で実行する StockTicker クラスのインスタンスを 1 つだけします。You only want one instance of the StockTicker class to run on the server, so you'll need to set up a reference from each StockTickerHub instance to the singleton StockTicker instance. 株価データには、トリガーの更新プログラム、StockTicker はハブ クラスではないために、クライアントにブロードキャストできる StockTicker クラスにあります。The StockTicker class has to be able to broadcast to clients because it has the stock data and triggers updates, but StockTicker is not a Hub class. そのため、StockTicker クラスは、SignalR ハブの接続コンテキスト オブジェクトへの参照を取得しています。Therefore, the StockTicker class has to get a reference to the SignalR Hub connection context object. クライアントにブロードキャストする SignalR 接続のコンテキスト オブジェクトを使用できます。It can then use the SignalR connection context object to broadcast to clients.

  1. ソリューション エクスプ ローラープロジェクトを右クリックし、クリックして、新しい項目の追加します。In Solution Explorer, right-click the project and click Add New Item.

  2. Visual Studio 2012 があれば、 ASP.NET および Web Tools 2012.2 Update、] をクリックしてWeb [ Visual c# を選択し、 SignalR ハブ クラス項目テンプレート。If you have Visual Studio 2012 with the ASP.NET and Web Tools 2012.2 Update, click Web under Visual C# and select the SignalR Hub Class item template. それ以外の場合、選択、クラステンプレート。Otherwise, select the Class template.

  3. 新しいクラスの名前StockTickerHub.cs、 をクリックし、追加します。Name the new class StockTickerHub.cs, and then click Add.

    StockTickerHub.cs を追加します。

  4. テンプレート コードを次のコードに置き換えます。Replace the template code with the following code:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using Microsoft.AspNet.SignalR;
    using Microsoft.AspNet.SignalR.Hubs;
    
    namespace SignalR.StockTicker
    {
        [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();
            }
        }
    }
    

    ハブメソッドは、クライアントは、サーバー上で呼び出すことができますを定義するクラスを使用します。The Hub class is used to define methods the clients can call on the server. 1 つのメソッドを定義する:GetAllStocks()します。You are defining one method: GetAllStocks(). クライアントは、最初に、サーバーに接続するときは、その現在の価格の株式のすべての一覧を取得するには、このメソッドを呼び出します。When a client initially connects to the server, it will call this method to get a list of all of the stocks with their current prices. メソッドは同期的に実行し、返すIEnumerable<Stock>メモリからデータを返すためです。The method can execute synchronously and return IEnumerable<Stock> because it is returning data from memory. 指定したかどうか、メソッドがデータベース検索など、web サービス呼び出しの待機を含むは何かの手順を実行してデータを取得する必要があるTask<IEnumerable<Stock>>非同期処理を有効にする戻り値として。If the method had to get the data by doing something that would involve waiting, such as a database lookup or a web service call, you would specify Task<IEnumerable<Stock>> as the return value to enable asynchronous processing. 詳細については、次を参照してください。 ASP.NET SignalR ハブ API ガイド - サーバーの非同期的に実行するタイミングします。For more information, see ASP.NET SignalR Hubs API Guide - Server - When to execute asynchronously.

    HubName 属性は、クライアントでの JavaScript コードでのハブの参照方法を指定します。The HubName attribute specifies how the Hub will be referenced in JavaScript code on the client. この属性を使用しない場合、クライアントに既定の名前は、ここで stockTickerHub 可能性のあるクラス名の camel 形式のバージョンです。The default name on the client if you don't use this attribute is a camel-cased version of the class name, which in this case would be stockTickerHub.

    StockTicker クラスを作成するときに、後で表示されます、としては、そのクラスのシングルトン インスタンスがその静的インスタンス プロパティに作成されます。As you'll see later when you create the StockTicker class, a singleton instance of that class is created in its static Instance property. StockTicker のシングルトン インスタンスまたは切断するには、接続のクライアントの数に関係なくメモリに残りますをそのインスタンスが GetAllStocks メソッドを使用して、現在の株価情報が返されます。That singleton instance of StockTicker remains in memory no matter how many clients connect or disconnect, and that instance is what the GetAllStocks method uses to return current stock information.

  5. プロジェクト フォルダーに新しいクラス ファイルを作成、名前を付けますStockTicker.cs、テンプレート コードを次のコードに置き換えます。Create a new class file in the project folder, name it StockTicker.cs, and then replace the template code with the following code:

    using System;
    using System.Collections.Concurrent;
    using System.Collections.Generic;
    using System.Threading;
    using Microsoft.AspNet.SignalR;
    using Microsoft.AspNet.SignalR.Hubs;
    
    namespace SignalR.StockTicker
    {
        public class StockTicker
        {
            // Singleton instance
            private 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 change
            private 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 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 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 udpate this stock or not
                var r = _updateOrNotRandom.NextDouble();
                if (r > .1)
                {
                    return false;
                }
    
                // Update the stock price by a random factor of the range percent
                var 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);
            }
    
        }
    }
    

    複数のスレッドが StockTicker コードの同じインスタンスを実行するため、スレッド セーフにする StockTicker クラスがあります。Since multiple threads will be running the same instance of StockTicker code, the StockTicker class has to be threadsafe.

    静的フィールドに、シングルトン インスタンスを格納します。Storing the singleton instance in a static field

    静的な初期化_コンス トラクターがプライベートとしてマークされているために、クラスでのインスタンスとインスタンスのプロパティをバックするインスタンス フィールドが作成できるクラスの唯一のインスタンス。The code initializes the static _instance field that backs the Instance property with an instance of the class, and this is the only instance of the class that can be created, because the constructor is marked as private. 遅延初期化の使用は、_するインスタンスの作成がスレッド セーフであることを確認しますが、パフォーマンス上の理由は、インスタンス フィールドです。Lazy initialization is used for the _instance field, not for performance reasons but to ensure that the instance creation is threadsafe.

    private readonly static Lazy<StockTicker> _instance = new Lazy<StockTicker>(() => new StockTicker(GlobalHost.ConnectionManager.GetHubContext<StockTickerHub>().Clients));
    
    public static StockTicker Instance
    {
        get
        {
            return _instance.Value;
        }
    }
    

    クライアントがサーバーに接続するたびに個別のスレッドで実行される StockTickerHub クラスの新しいインスタンスする StockTickerHub クラスで既に見たよう StockTicker のシングルトン インスタンスが StockTicker.Instance の静的プロパティから取得します。Each time a client connects to the server, a new instance of the StockTickerHub class running in a separate thread gets the StockTicker singleton instance from the StockTicker.Instance static property, as you saw earlier in the StockTickerHub class.

    ConcurrentDictionary の株価データを格納します。Storing stock data in a ConcurrentDictionary

    コンス トラクターによって初期化、_いくつかのサンプルの株価データ、および GetAllStocks stocks コレクションが、株式を返します。The constructor initializes the _stocks collection with some sample stock data, and GetAllStocks returns the stocks. 既に説明したよう株式のこのコレクションがさらにクライアントが呼び出すことができる、ハブ クラスにサーバーのメソッドである StockTickerHub.GetAllStocks によって返されます。As you saw earlier, this collection of stocks is in turn returned by StockTickerHub.GetAllStocks which is a server method in the Hub class that clients can call.

    private readonly ConcurrentDictionary<string, Stock> _stocks = new ConcurrentDictionary<string, Stock>();
    
    private StockTicker(IHubConnectionContext 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 IEnumerable<Stock> GetAllStocks()
    {
        return _stocks.Values;
    }
    

    Stocks コレクションとは見なさ、 ConcurrentDictionaryスレッド セーフの型。The stocks collection is defined as a ConcurrentDictionary type for thread safety. 別の方法として使用できます、ディクショナリオブジェクトし、それを変更するときに明示的にディクショナリをロックします。As an alternative, you could use a Dictionary object and explicitly lock the dictionary when you make changes to it.

    このサンプル アプリケーションは OK StockTicker インスタンスが破棄されたときに、データが失われるとアプリケーション データをメモリに格納します。For this sample application, it's OK to store application data in memory and to lose the data when the StockTicker instance is disposed. 実際のアプリケーションでは、データベースなどのバックエンド データ ストアと動作します。In a real application you would work with a back-end data store such as a database.

    株価を定期的に更新Periodically updating stock prices

    コンス トラクターは、ランダムな単位で株価を更新するメソッドを定期的に呼び出すタイマー オブジェクトを開始します。The constructor starts up a Timer object that periodically calls methods that update stock prices on a random basis.

    _timer = new Timer(UpdateStockPrices, null, _updateInterval, _updateInterval);
    
    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 not
        var r = _updateOrNotRandom.NextDouble();
        if (r > .1)
        {
            return false;
        }
    
        // Update the stock price by a random factor of the range percent
        var 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;
    }
    

    UpdateStockPrices は、state パラメーターで null を渡すと、タイマーによって呼び出されます。UpdateStockPrices is called by the Timer, which passes in null in the state parameter. 価格を更新する前にロックを取得、 _updateStockPricesLock オブジェクト。Before updating prices, a lock is taken on the _updateStockPricesLock object. 別のスレッドが価格を更新中で既にと、各株式の一覧で TryUpdateStockPrice を呼び出すかどうか、コードを確認します。The code checks if another thread is already updating prices, and then it calls TryUpdateStockPrice on each stock in the list. TryUpdateStockPrice メソッドは、株価を変更するかどうかを決定し、これを変更する量。The TryUpdateStockPrice method decides whether to change the stock price, and how much to change it. 株式の価格が変更された場合は、接続されているすべてのクライアントに株価の変更をブロードキャストする BroadcastStockPrice が呼び出されます。If the stock price is changed, BroadcastStockPrice is called to broadcast the stock price change to all connected clients.

    _UpdatingStockPrices フラグがマーク揮発性へのアクセスがスレッド セーフであることを確認します。The _updatingStockPrices flag is marked as volatile to ensure that access to it is threadsafe.

    private volatile bool _updatingStockPrices = false;
    

    実際のアプリケーションで TryUpdateStockPrice メソッドが、価格を検索する web サービスを呼び出すとこのコードでは、ランダムに変更するのに乱数ジェネレーターを使用します。In a real application, the TryUpdateStockPrice method would call a web service to look up the price; in this code it uses a random number generator to make changes randomly.

    StockTicker クラスは、クライアントにブロードキャストできるように、SignalR のコンテキストを取得します。Getting the SignalR context so that the StockTicker class can broadcast to clients

    料金の変更は、StockTicker オブジェクトでは、ここに送信される、ためこれは、接続されているすべてのクライアントで、updateStockPrice メソッドを呼び出す必要があるオブジェクト。Because the price changes originate here in the StockTicker object, this is the object that needs to call an updateStockPrice method on all connected clients. クライアントのメソッドを呼び出すための API のあるハブ クラスでは、StockTicker ハブ クラスから派生していないと、任意のハブ オブジェクトへの参照はありません。In a Hub class you have an API for calling client methods, but StockTicker does not derive from the Hub class and does not have a reference to any Hub object. そのため、接続されているクライアントにブロードキャストするためには、StockTickerHub クラスの SignalR コンテキストのインスタンスを取得し、クライアントでメソッドの呼び出しに使用するに StockTicker クラスがあります。Therefore, in order to broadcast to connected clients, the StockTicker class has to get the SignalR context instance for the StockTickerHub class and use that to call methods on clients.

    コンス トラクターに渡すを参照する、シングルトン クラス インスタンスを作成するときに、コードが SignalR コンテキストへの参照を取得し、コンス トラクターは、クライアントのプロパティ内に配置します。The code gets a reference to the SignalR context when it creates the singleton class instance, passes that reference to the constructor, and the constructor puts it in the Clients property.

    2 つの理由の 1 回だけ、コンテキストを取得する理由がある: 負荷の高い操作では、コンテキストを取得して、1 回取得することにより、クライアントに送信されるメッセージの目的の順序が保持されます。There are two reasons why you want to get the context just once: getting the context is an expensive operation, and getting it once ensures that the intended order of messages sent to clients is preserved.

    private readonly static Lazy<StockTicker> _instance =
        new Lazy<StockTicker>(() => new StockTicker(GlobalHost.ConnectionManager.GetHubContext<StockTickerHub>().Clients));
    
    private StockTicker(IHubConnectionContext clients)
    {
        Clients = clients;
    
        // Remainder of constructor ...
    }
    
    private IHubConnectionContext Clients
    {
        get;
        set;
    }
    
    private void BroadcastStockPrice(Stock stock)
    {
        Clients.All.updateStockPrice(stock);
    }
    

    コンテキストのクライアント プロパティを取得し、StockTickerClient プロパティで、ハブ クラスの場合と同様、同じ検索するメソッドを呼び出すクライアント コードを記述することができます。Getting the Clients property of the context and putting it in the StockTickerClient property lets you write code to call client methods that looks the same as it would in a Hub class. たとえば、すべてのクライアントにブロードキャストする Clients.All.updateStockPrice(stock) を記述できます。For instance, to broadcast to all clients you can write Clients.All.updateStockPrice(stock).

    BroadcastStockPrice で呼び出している updateStockPrice メソッドがまだ存在しません。後で追加するクライアントで実行されるコードを記述するときにします。The updateStockPrice method that you are calling in BroadcastStockPrice doesn't exist yet; you'll add it later when you write code that runs on the client. Clients.All は動的で、実行時に、式が評価されることを意味しているために、updateStockPrice ここを参照できます。You can refer to updateStockPrice here because Clients.All is dynamic, which means the expression will be evaluated at runtime. このメソッドの呼び出しが実行されると、SignalR はクライアントに送信メソッド名とパラメーターの値、およびクライアントに updateStockPrice という名前のメソッドがある場合は、そのメソッドが呼び出され、それに渡されるパラメーターの値。When this method call executes, SignalR will send the method name and the parameter value to the client, and if the client has a method named updateStockPrice, that method will be called and the parameter value will be passed to it.

    Clients.All では、すべてのクライアントに送信を意味します。Clients.All means send to all clients. SignalR では、その他のオプションのクライアントまたはクライアントに送信するグループを指定できます。SignalR gives you other options to specify which clients or groups of clients to send to. 詳細については、次を参照してください。 HubConnectionContextします。For more information, see HubConnectionContext.

SignalR のルートを登録します。Register the SignalR route

サーバーは、途中受信および SignalR への直接する URL を把握する必要があります。The server needs to know which URL to intercept and direct to SignalR. いくつかのコードを追加することを行う、 Global.asaxファイル。To do that you'll add some code to the Global.asax file.

  1. ソリューション エクスプ ローラープロジェクトを右クリックし、クリックして新しい項目の追加します。In Solution Explorer, right-click the project, and then click Add New Item.

  2. 選択、グローバル アプリケーション クラス項目テンプレートをクリックして追加します。Select the Global Application Class item template, and then click Add.

    Global.asax を追加します。

  3. SignalR のルート登録のコードをアプリケーションに追加_メソッドを開始します。Add the SignalR route registration code to the Application_Start method:

    protected void Application_Start(object sender, EventArgs e)
    {
        RouteTable.Routes.MapHubs();
    }
    

    SignalR のすべてのトラフィックのベース URL は、既定では、"/signalr"、「/signalr ハブ」が、アプリケーションであるすべてのハブ プロキシを定義する、動的に生成された JavaScript ファイルを取得するために使用されます。By default, the base URL for all SignalR traffic is "/signalr", and "/signalr/hubs" is used to retrieve a dynamically generated JavaScript file that defines proxies for all the Hubs you have in your application. MapHubs メソッドにはインスタンスで別の基本 URL と特定の SignalR オプションを指定できるオーバー ロードが含まれています、 HubConfigurationクラス。The MapHubs method includes overloads that let you specify a different base URL and certain SignalR options in an instance of the HubConfiguration class.

  4. 使用して、追加、ファイルの上部にあるステートメント。Add a using statement at the top of the file:

    using System.Web.Routing;
    
  5. 保存して閉じます、 Global.asaxファイルを開き、プロジェクトをビルドします。Save and close the Global.asax file, and build the project.

サーバー コードのセットアップが完了しました。You have now completed setting up the server code. 次のセクションでは、クライアントを設定します。In the next section you'll set up the client.

クライアント コードを設定します。Set up the client code

  1. プロジェクト フォルダーに新しい HTML ファイルを作成し、名前StockTicker.htmlします。Create a new HTML file in the project folder, and name it StockTicker.html.

  2. テンプレート コードを次のコードに置き換えます。Replace the template code with the following code:

    <!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-1.8.2.min.js" ></script>
        <!--Reference the SignalR library. -->
        <script src="/Scripts/jquery.signalR-1.0.1.js"></script>
        <!--Reference the autogenerated SignalR hub script. -->
        <script src="/signalr/hubs"></script>
        <!--Reference the StockTicker script. -->
        <script src="StockTicker.js"></script>
    </body>
    </html>
    

    HTML では、5 つの列、ヘッダー行では、5 つすべての列にまたがる単一のセルにデータ行とテーブルを作成します。The HTML creates a table with 5 columns, a header row, and a data row with a single cell that spans all 5 columns. データ行は、「読み込み中...」が表示され、アプリケーションの起動時に一時的にのみ表示されます。The data row displays "loading..." and will only be shown momentarily when the application starts. JavaScript コードはその行を削除して、サーバーから取得した株価データでその場所の行に追加します。JavaScript code will remove that row and add in its place rows with stock data retrieved from the server.

    スクリプト タグは、jQuery スクリプト ファイル、SignalR core のスクリプト ファイル、SignalR プロキシ スクリプト ファイル、および後で作成する StockTicker スクリプト ファイルを指定します。The script tags specify the jQuery script file, the SignalR core script file, the SignalR proxies script file, and a StockTicker script file that you'll create later. 「/Signalr ハブ」の URL を指定するには、SignalR プロキシ スクリプト ファイルが動的に生成され、StockTickerHub.GetAllStocks をここで、ハブ クラス上のメソッドをプロキシのメソッドを定義します。The SignalR proxies script file, which specifies the "/signalr/hubs" URL, is dynamically generated and defines proxy methods for the methods on the Hub class, in this case for StockTickerHub.GetAllStocks. 使用してこの JavaScript ファイルが手動で生成できる場合は、 SignalR ユーティリティMapHubs メソッドの呼び出しで動的ファイルの作成を無効にするとします。If you prefer, you can generate this JavaScript file manually by using SignalR Utilities and disable dynamic file creation in the MapHubs method call.

  3. Important

    JavaScript ファイルを参照しているかどうかを確認StockTicker.htmlが正しい。Make sure that the JavaScript file references in StockTicker.html are correct. つまり、jQuery バージョン、スクリプト タグ (例では 1.8.2) では、プロジェクトの jQuery バージョンと同じであることを確認スクリプトフォルダー、スクリプト タグで SignalR バージョンは、SignalR と同じかどうかを確認してプロジェクトのバージョンスクリプトフォルダー。That is, make sure that the jQuery version in your script tag (1.8.2 in the example) is the same as the jQuery version in your project's Scripts folder, and make sure that the SignalR version in your script tag is the same as the SignalR version in your project's Scripts folder. 必要な場合は、スクリプト タグ内のファイル名を変更します。Change the file names in the script tags if necessary.

  4. ソリューション エクスプ ローラー、右クリックStockTicker.html、 をクリックし、スタート ページとして設定します。In Solution Explorer, right-click StockTicker.html, and then click Set as Start Page.

  5. プロジェクト フォルダーで新しい JavaScript ファイルを作成し、名前StockTicker.js.Create a new JavaScript file in the project folder and name it StockTicker.js..

  6. テンプレート コードを次のコードに置き換えます。Replace the template code with the following code:

    // 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 proxy
            up = '▲',
            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 call
        ticker.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);
    
    });
    

    $.connection は SignalR プロキシを表します。$.connection refers to the SignalR proxies. コードでは、StockTickerHub クラスのプロキシへの参照を取得し、ティッカー変数内に配置します。The code gets a reference to the proxy for the StockTickerHub class and puts it in the ticker variable. プロキシの名前は、[HubName] 属性によって設定された名前を示します。The proxy name is the name that was set by the [HubName] attribute:

    var ticker = $.connection.stockTickerMini
    
    [HubName("stockTickerMini")]
    public class StockTickerHub : Hub
    

    すべての変数と関数を定義した後、ファイル内のコードの最後の行は SignalR の start 関数を呼び出すことによって、SignalR 接続を初期化します。After all the variables and functions are defined, the last line of code in the file initializes the SignalR connection by calling the SignalR start function. Start 関数が非同期的に実行し、返します、 jQuery 遅延オブジェクト、することができる非同期操作が完了したときに呼び出す関数を指定する元に戻す関数を呼び出すことができます.The start function executes asynchronously and returns a jQuery Deferred object, which means you can call the done function to specify the function to call when the asynchronous operation is completed..

    $.connection.hub.start().done(init);
    

    Init 関数は、ストックのテーブルを更新するサーバーが返す情報を使用して、サーバーで getAllStocks 関数を呼び出します。The init function calls the getAllStocks function on the server and uses the information that the server returns to update the stock table. 既定では、あるメソッド名は pascal 形式で表記するサーバーがクライアントで camel 規約に従った大文字を使用することを確認します。Notice that by default, you have to use camel casing on the client although the method name is pascal-cased on the server. キャメル形式の規則は、オブジェクトではなく、メソッドにのみ適用されます。The camel-casing rule only applies to methods, not objects. たとえば、在庫を参照してください。シンボルと在庫です。価格、stock.symbol または stock.price します。For example, you refer to stock.Symbol and stock.Price, not stock.symbol or stock.price.

    function init() {
        ticker.server.getAllStocks().done(function (stocks) {
            $stockTableBody.empty();
            $.each(stocks, function () {
                var stock = formatStock(this);
                $stockTableBody.append(rowTemplate.supplant(stock));
            });
        });
    }
    
    public IEnumerable<Stock> GetAllStocks()
    {
        return _stockTicker.GetAllStocks();
    }
    

    クライアントでは、pascal 形式の大文字と小文字を使用するかは HubMethodName 属性でのハブ メソッドを修飾することがまったく異なるメソッドの名前を使用する場合は、HubName 属性を持つハブ クラス自体を装飾します。If you wanted to use pascal casing on the client, or if you wanted to use a completely different method name, you could decorate the Hub method with the HubMethodName attribute the same way you decorated the Hub class itself with the HubName attribute.

    Init メソッドでの HTML テーブルの行はストックのオブジェクトの書式設定のプロパティを呼び出し元 formatStock によってサーバーから受け取った各株オブジェクトに対して作成され、脅かすを呼び出した (の上部で定義されているStockTicker.js) オブジェクトのストック プロパティの値を持つ rowTemplate 変数内のプレース ホルダーを置き換えます。In the init method, HTML for a table row is created for each stock object received from the server by calling formatStock to format properties of the stock object, and then by calling supplant (which is defined at the top of StockTicker.js) to replace placeholders in the rowTemplate variable with the stock object property values. 結果の HTML は、株価のテーブルに追加されます。The resulting HTML is then appended to the stock table.

    非同期の start 関数の完了後に実行されるコールバック関数として渡すことによって、init を呼び出します。You call init by passing it in as a callback function that executes after the asynchronous start function completes. Init を呼び出すと、開始を呼び出した後、別の JavaScript ステートメントとして、接続の確立を完了するのには start 関数を待たずにすぐに実行があるため、関数は失敗します。If you called init as a separate JavaScript statement after calling start, the function would fail because it would execute immediately without waiting for the start function to finish establishing the connection. その場合は、init 関数では、サーバー接続が確立される前に、getAllStocks 関数を呼び出すとします。In that case, the init function would try to call the getAllStocks function before the server connection is established.

    サーバー、株の価格が変更されると、接続されているクライアントで、updateStockPrice を呼び出します。When the server changes a stock's price, it calls the updateStockPrice on connected clients. 関数は、使用できるように、呼び出しに、サーバーから stockTicker プロキシのクライアントのプロパティに追加されます。The function is added to the client property of the stockTicker proxy in order to make it available to calls from the server.

    ticker.client.updateStockPrice = function (stock) {
        var displayStock = formatStock(stock),
            $row = $(rowTemplate.supplant(displayStock));
    
        $stockTableBody.find('tr[data-symbol=' + stock.Symbol + ']')
            .replaceWith($row);
        }
    

    UpdateStockPrice 関数は、テーブルの行に init 関数と同様、サーバーから受け取ったストック オブジェクトを書式設定します。The updateStockPrice function formats a stock object received from the server into a table row the same way as in the init function. ただし、テーブルに行を追加することではなく、表内の株式の現在の行を検索し、その行を新しいものに置き換えます。However, instead of appending the row to the table, it finds the stock's current row in the table and replaces that row with the new one.

アプリケーションをテストするTest the application

  1. F5 キーを押して、デバッグ モードでアプリケーションを実行します。Press F5 to run the application in debug mode.

    ストックの表に、最初に表示されます、「読み込み中...」の行、初期の株価データを表示すると、短い遅延の後し、株式の価格を変更します。The stock table initially displays the "loading..." line, then after a short delay the initial stock data is displayed, and then the stock prices start to change.

    [読み込み中]

    初期の在庫テーブル

    サーバーからの変更を受け取るストック テーブル

  2. ブラウザーのアドレス バーから URL をコピーして、1 つまたは複数の新しいブラウザー ウィンドウに貼り付けます。Copy the URL from the browser address bar and paste it into one or more new browser window(s).

    初期の株価表示は、最初のブラウザーと同じと同時に変更が行われます。The initial stock display is the same as the first browser and changes happen simultaneously.

  3. すべてのブラウザーを閉じるし、新しいブラウザーを開いて、同じ URL に移動します。Close all browsers and open a new browser, then go to the same URL.

    StockTicker シングルトン オブジェクトは、在庫表の表示が、株式を変更し続けていることを示しています、サーバーで実行を続けています。The StockTicker singleton object has continued to run in the server, so the stock table display shows that the stocks have continued to change. (図形を変更、初期テーブルのゼロは表示されません)。(You don't see the initial table with zero change figures.)

  4. ブラウザーを閉じます。Close the browser.

ログの有効化Enable logging

SignalR では、トラブルシューティングで支援するために、クライアントで有効にできる組み込みのログ記録関数があります。SignalR has a built-in logging function that you can enable on the client to aid in troubleshooting. このセクションでは、ログ記録を有効にし、ログを知る方法を次のトランスポート メソッドの SignalR を使用して表示する例を参照してください。In this section you enable logging and see examples that show how logs tell you which of the following transport methods SignalR is using:

特定の接続では、SignalR は、サーバーとクライアントの両方をサポートする最適なトランスポートの方法を選択します。For any given connection, SignalR chooses the best transport method that both the server and the client support.

  1. 開いているStockTicker.jsし、ファイルの最後に、接続を初期化するコードの直前のログ記録を有効にするコードの行を追加します。Open StockTicker.js and add a line of code to enable logging immediately before the code that initializes the connection at the end of the file:

    // Start the connection
    $.connection.hub.logging = true;
    $.connection.hub.start().done(init);
    
  2. F5 キーを押してプロジェクトを実行します。Press F5 to run the project.

  3. ブラウザーの開発者ツール ウィンドウを開きし、ログを表示するコンソールを選択します。Open your browser's developer tools window, and select the Console to see the logs. 新しい接続の転送方法をネゴシエートする Signalr のログを表示するページを更新する必要があります。You might have to refresh the page to see the logs of Signalr negotiating the transport method for a new connection.

    Windows 8 (IIS 8) で Internet Explorer 10 を実行している場合は、Websocket は、トランスポート メソッド。If you are running Internet Explorer 10 on Windows 8 (IIS 8), the transport method is WebSockets.

    IE 10 IIS 8 コンソールします。

    Windows 7 (IIS 7.5) で Internet Explorer 10 を実行している場合は、iframe はトランスポート メソッドです。If you are running Internet Explorer 10 on Windows 7 (IIS 7.5), the transport method is iframe.

    IE 10 コンソールで、IIS 7.5

    Firefox の場合、コンソール ウィンドウを取得する Firebug アドインのインストールします。In Firefox, install the Firebug add-in to get a Console window. Firefox 19 を Windows 8 (IIS 8) を実行する場合は、Websocket はトランスポート メソッドです。If you are running Firefox 19 on Windows 8 (IIS 8), the transport method is WebSockets.

    Firefox 19 IIS 8 Websocket

    Firefox 19 を Windows 7 (IIS 7.5) を実行する場合は、サーバー送信イベントが、トランスポート メソッド。If you are running Firefox 19 on Windows 7 (IIS 7.5), the transport method is server-sent events.

    Firefox 19 IIS 7.5 コンソールします。

インストールして、完全な StockTicker サンプルを確認してください。Install and review the full StockTicker sample

StockTicker アプリケーションがインストールされている、 Microsoft.AspNet.SignalR.Sample NuGet パッケージには、最初から作成した簡略化されたバージョンより多くの機能が含まれています。The StockTicker application that is installed by the Microsoft.AspNet.SignalR.Sample NuGet package includes more features than the simplified version that you just created from scratch. チュートリアルのこのセクションでは、NuGet パッケージをインストールし、新機能とそれらを実装するコードを確認します。In this section of the tutorial, you install the NuGet package and review the new features and the code that implements them.

SignalR.Sample NuGet パッケージをインストールします。Install the SignalR.Sample NuGet package

  1. ソリューション エクスプ ローラープロジェクトを右クリックし、クリックして、 NuGet パッケージの管理します。In Solution Explorer, right-click the project and click Manage NuGet Packages.

  2. NuGet パッケージの管理ダイアログ ボックスで、をクリックしてオンライン、入力SignalR.Sampleで、オンライン検索ボックス、および順にクリックしますインストールで、 SignalR.Sampleパッケージ。In the Manage NuGet Packages dialog box, click Online, enter SignalR.Sample in the Search Online box, and then click Install in the SignalR.Sample package.

    SignalR.Sample パッケージをインストールします。

  3. Global.asaxファイル、コメント アウト、RouteTable.Routes.MapHubs(); 行の前にアプリケーションで追加した_メソッドを開始します。In the Global.asax file, comment out the RouteTable.Routes.MapHubs(); line that you added earlier in the Application_Start method.

    コードでは、 Global.asax SignalR.Sample パッケージで SignalR のルートを登録するためには必要がなくなったら、アプリ_Start/RegisterHubs.csファイル。The code in Global.asax is no longer needed because the SignalR.Sample package registers the SignalR route in the App_Start/RegisterHubs.cs file:

    [assembly: WebActivator.PreApplicationStartMethod(typeof(SignalR.StockTicker.RegisterHubs), "Start")]
    
    namespace SignalR.StockTicker
    {
        public static class RegisterHubs
        {
            public static void Start()
            {
                // Register the default hubs route: ~/signalr/hubs
                RouteTable.Routes.MapHubs();
            }
        }
    }
    

    アセンブリ属性によって参照される WebActivator クラスは、SignalR.Sample パッケージの依存関係としてインストールされている WebActivatorEx NuGet パッケージに含まれます。The WebActivator class that is referenced by the assembly attribute is included in the WebActivatorEx NuGet package, which is installed as a dependency of the SignalR.Sample package.

  4. ソリューション エクスプ ローラー、展開、 SignalR.Sample SignalR.Sample パッケージをインストールすることによって作成されたフォルダーです。In Solution Explorer, expand the SignalR.Sample folder which was created by installing the SignalR.Sample package.

  5. SignalR.Sampleフォルダーを右クリックしてStockTicker.html、 をクリックし、スタート ページとして設定In the SignalR.Sample folder, right-click StockTicker.html, and then click Set As Start Page.

    Note

    SignalR.Sample NuGet のインストール パッケージは内にある jQuery のバージョンを変更可能性があります、スクリプトフォルダー。Installing The SignalR.Sample NuGet package might change the version of jQuery that you have in your Scripts folder. 新しいStockTicker.htmlでパッケージをインストールするファイル、 SignalR.Sampleフォルダーが、元のを実行する場合は、パッケージをインストールするjQueryバージョンとの同期にStockTicker.htmlファイルを再び、最初にスクリプト タグ内の jQuery 参照を更新する必要があります。The new StockTicker.html file that the package installs in the SignalR.Sample folder will be in sync with the jQuery version that the package installs, but if you want to run your original StockTicker.html file again, you might have to update the jQuery reference in the script tag first.

アプリケーションの実行Run the application

  1. F5 キーを押してアプリケーションを実行します。Press F5 to run the application.

    先ほど見たグリッド、だけでなくは、完全な株価表示器のアプリケーションには、同じの株価データを表示する水平方向にスクロール ウィンドウが表示されます。In addition to the grid that you saw earlier, the full stock ticker application shows a horizontally scrolling window that displays the same stock data. 最初にアプリケーションを実行して、「市場」は"closed"静的グリッドとティッカー ウィンドウ スクロールはありませんを参照してください。When you run the application for the first time, the "market" is "closed" and you see a static grid and a ticker window that isn't scrolling.

    StockTicker 画面の開始

    クリックするとオープン市場株式ティッカーの Liveを水平方向にスクロール ボックスを起動し、サーバーがランダムに株価の変更を定期的にブロードキャストする開始します。When you click Open Market, the Live Stock Ticker box starts to scroll horizontally, and the server starts to periodically broadcast stock price changes on a random basis. 株価たびに変更する場合に、両方、在庫表の Liveグリッドと株式ティッカーの Liveボックスが更新されます。Each time a stock price changes, both the Live Stock Table grid and the Live Stock Ticker box are updated. 株式の価格の変更が正、素材は緑の背景で表示され、背景が赤の素材が示すように、変更は、負の値が、場合。When a stock's price change is positive, the stock is shown with a green background, and when the change is negative, the stock is shown with a red background.

    StockTicker アプリ市場を開く

    閉じる市場ボタンは、変更を停止し、ティッカー スクロールが停止し、リセットの料金の変更を開始する前にボタンが初期状態にすべての株価データをリセットします。The Close Market button stops the changes and stops the ticker scrolling, and the Reset button resets all stock data to the initial state before price changes started. 複数のブラウザー ウィンドウを開くし、同じ URL に移動する場合、各ブラウザーで同時に動的に更新される同じデータを参照してください。If you open more browser windows and go to the same URL, you see the same data dynamically updated at the same time in each browser. クリックすると、ボタンのいずれかのブラウザーと同時に同じ方法もあります。When you click one of the buttons, all browsers respond the same way at the same time.

ライブの株式相場表示Live Stock Ticker display

株式ティッカーの Liveディスプレイが CSS スタイルによって 1 行に書式設定されている div 要素の順序なしのリスト。The Live Stock Ticker display is an unordered list in a div element that is formatted into a single line by CSS styles. ティッカーは初期化され、テーブルと同様の更新: 内のプレース ホルダーを置き換えることで、 <li>テンプレート文字列と動的に追加する、 <li>要素を<ul>要素。The ticker is initialized and updated the same way as the table: by replacing placeholders in a <li> template string and dynamically adding the <li> elements to the <ul> element. Div 内で順序付けられていない一覧の左余白を変更するため、jQuery アニメーション化する関数を使用して、実行は、スクロールThe scrolling is performed by using the jQuery animate function to vary the margin-left of the unordered list within the div.

株価情報 HTML:The stock ticker HTML:

<h2>Live Stock Ticker</h2>
<div id="stockTicker">
    <div class="inner">
        <ul>
            <li class="loading">loading...</li>
        </ul>
    </div>
</div>

株価表示器 CSS で:The stock ticker CSS:

#stockTicker {
    overflow: hidden;
    width: 450px;
    height: 24px;
    border: 1px solid #999;
    }

    #stockTicker .inner {
        width: 9999px;
    }

    #stockTicker ul {
        display: inline-block;
        list-style-type: none;
        margin: 0;
        padding: 0;
    }

    #stockTicker li {
        display: inline-block;
        margin-right: 8px;   
    }

    /*<li data-symbol="{Symbol}"><span class="symbol">{Symbol}</span><span class="price">{Price}</span><span class="change">{PercentChange}</span></li>*/
    #stockTicker .symbol {
        font-weight: bold;
    }

    #stockTicker .change {
        font-style: italic;
    }

JQuery コードがスクロールします。The jQuery code that makes it scroll:

function scrollTicker() {
    var w = $stockTickerUl.width();
    $stockTickerUl.css({ marginLeft: w });
    $stockTickerUl.animate({ marginLeft: -w }, 15000, 'linear', scrollTicker);
}

クライアントが呼び出すことができる、サーバーで追加のメソッドAdditional methods on the server that the client can call

StockTickerHub クラスには、クライアントが呼び出すことができる 4 つの追加のメソッドを定義します。The StockTickerHub class defines four additional methods that the client can call:

public string GetMarketState()
{
    return _stockTicker.MarketState.ToString();
}

public void OpenMarket()
{
    _stockTicker.OpenMarket();
}

public void CloseMarket()
{
    _stockTicker.CloseMarket();
}

public void Reset()
{
    _stockTicker.Reset();
}

OpenMarket、CloseMarket、およびリセットは、ページの上部にあるボタンへの応答で呼び出されます。OpenMarket, CloseMarket, and Reset are called in response to the buttons at the top of the page. これらは、すべてのクライアントにすぐに反映される状態の変化をトリガーする 1 つのクライアントのパターンを示します。They demonstrate the pattern of one client triggering a change in state that is immediately propagated to all clients. これらの各メソッドでメソッドを呼び出し、StockTicker クラス市場の状態を変更して、新しい状態をブロードキャストし、その効果。Each of these methods calls a method in the StockTicker class that effects the market state change and then broadcasts the new state.

StockTicker クラスで MarketState 列挙型の値を返す MarketState プロパティで、市場の状態が維持されます。In the StockTicker class, the state of the market is maintained by a MarketState property that returns a MarketState enum value:

public MarketState MarketState
{
    get { return _marketState; }
    private set { _marketState = value; }
}

public enum MarketState
{
    Closed,
    Open
}

各市場の状態を変更する方法は、ロック ブロックの内部 StockTicker クラスがあるスレッド セーフのためです。Each of the methods that change the market state do so inside a lock block because the StockTicker class has to be threadsafe:

public void OpenMarket()
{
    lock (_marketStateLock)
    {
        if (MarketState != MarketState.Open)
        {
            _timer = new Timer(UpdateStockPrices, null, _updateInterval, _updateInterval);
            MarketState = MarketState.Open;
            BroadcastMarketStateChange(MarketState.Open);
        }
    }
}

public void CloseMarket()
{
    lock (_marketStateLock)
    {
        if (MarketState == MarketState.Open)
        {
            if (_timer != null)
            {
                _timer.Dispose();
            }
            MarketState = MarketState.Closed;
            BroadcastMarketStateChange(MarketState.Closed);
        }
    }
}

public void Reset()
{
    lock (_marketStateLock)
    {
        if (MarketState != MarketState.Closed)
        {
            throw new InvalidOperationException("Market must be closed before it can be reset.");
        }
        LoadDefaultStocks();
        BroadcastMarketReset();
    }
}

このコードが、スレッド セーフであることを確認する、 _MarketState プロパティをバックする marketState フィールドは、volatile としてマークTo ensure that this code is threadsafe, the _marketState field that backs the MarketState property is marked as volatile,

private volatile MarketState _marketState;

BroadcastMarketStateChange と BroadcastMarketReset メソッドは、クライアントで定義されている別のメソッドを呼び出す点を既に確認した BroadcastStockPrice メソッドに似ています。The BroadcastMarketStateChange and BroadcastMarketReset methods are similar to the BroadcastStockPrice method that you already saw, except they call different methods defined at the client:

private void BroadcastMarketStateChange(MarketState marketState)
{
    switch (marketState)
    {
        case MarketState.Open:
            Clients.All.marketOpened();
            break;
        case MarketState.Closed:
            Clients.All.marketClosed();
            break;
        default:
            break;
    }
}

private void BroadcastMarketReset()
{
    Clients.All.marketReset();
}

サーバーが呼び出すことができるクライアントの追加の関数Additional functions on the client that the server can call

UpdateStockPrice 関数は、グリッドとティッカーの表示の両方を処理して、赤、緑の色をフラッシュする jQuery.Color を使用してください。The updateStockPrice function now handles both the grid and the ticker display, and it uses jQuery.Color to flash red and green colors.

新しい関数でSignalR.StockTicker.js有効にして、ボタンがに基づいて無効にする市場の状態や、停止やティッカー ウィンドウ水平スクロールを開始します。New functions in SignalR.StockTicker.js enable and disable the buttons based on market state, and they stop or start the ticker window horizontal scrolling. Ticker.client に複数の関数が追加されているため、 jQuery 関数を拡張するに追加するために使用します。Since multiple functions are being added to ticker.client, the jQuery extend function is used to add them.

$.extend(ticker.client, {
    updateStockPrice: function (stock) {
        var displayStock = formatStock(stock),
            $row = $(rowTemplate.supplant(displayStock)),
            $li = $(liTemplate.supplant(displayStock)),
            bg = stock.LastChange === 0
                ? '255,216,0' // yellow
                : stock.LastChange > 0
                    ? '154,240,117' // green
                    : '255,148,148'; // red

        $stockTableBody.find('tr[data-symbol=' + stock.Symbol + ']')
            .replaceWith($row);
        $stockTickerUl.find('li[data-symbol=' + stock.Symbol + ']')
            .replaceWith($li);

        $row.flash(bg, 1000);
        $li.flash(bg, 1000);
    },

    marketOpened: function () {
        $("#open").prop("disabled", true);
        $("#close").prop("disabled", false);
        $("#reset").prop("disabled", true);
        scrollTicker();
    },

    marketClosed: function () {
        $("#open").prop("disabled", false);
        $("#close").prop("disabled", true);
        $("#reset").prop("disabled", false);
        stopTicker();
    },

    marketReset: function () {
        return init();
    }
});

接続の確立後に追加のクライアントのセットアップAdditional client setup after establishing the connection

追加の作業を行うには、クライアント接続を確立した後: オープンかクローズ、適切な marketOpened または marketClosed 関数を呼び出すし、ボタンにサーバー メソッドの呼び出しをアタッチするには、市場がかどうかかを確認します。After the client establishes the connection, it has some additional work to do: find out if the market is open or closed in order to call the appropriate marketOpened or marketClosed function, and attach the server method calls to the buttons.

$.connection.hub.start()
    .pipe(init)
    .pipe(function () {
        return ticker.server.getMarketState();
    })
    .done(function (state) {
        if (state === 'Open') {
            ticker.client.marketOpened();
        } else {
            ticker.client.marketClosed();
        }

        // Wire up the buttons
        $("#open").click(function () {
            ticker.server.openMarket();
        });

        $("#close").click(function () {
            ticker.server.closeMarket();
        });

        $("#reset").click(function () {
            ticker.server.reset();
        });
    });

サーバー メソッドがないワイヤード (有線) までボタンまで、接続が確立されると、利用される前にサーバー メソッドを呼び出すしようとすることはできません、コードを。The server methods are not wired up to the buttons until after the connection is established, so that the code can't try to call the server methods before they are available.

次の手順Next steps

このチュートリアルでは、接続されているすべてのクライアント、定期的と任意のクライアントからの通知に応答の両方に、サーバーからメッセージをブロードキャストする SignalR アプリケーションをプログラミングする方法を学習できました。In this tutorial you've learned how to program a SignalR application that broadcasts messages from the server to all connected clients, both on a periodic basis and in response to notifications from any client. マルチ スレッドのシングルトン インスタンスを使用して、サーバーの状態を保持するパターンも、マルチ プレーヤー オンライン ゲーム シナリオで使用こともできます。The pattern of using a multi-threaded singleton instance to maintain server state can also be also used in multi-player online game scenarios. 例については、次を参照してください。 SignalR に基づいている ShootR ゲームします。For an example, see the ShootR game that is based on SignalR.

ピア ツー ピア通信シナリオを示すチュートリアルについては、次を参照してください。 SignalR の概要SignalR によるリアルタイムの更新します。For tutorials that show peer-to-peer communication scenarios, see Getting Started with SignalR and Real-Time Updating with SignalR.

SignalR 開発のより高度な概念については、SignalR のソース コードおよびリソースは、次のサイトを参照してください。To learn more advanced SignalR development concepts, visit the following sites for SignalR source code and resources: