チュートリアル: SignalR 2 によるブロードキャスト サーバーTutorial: Server broadcast with SignalR 2

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 2 を使用してサーバー ブロードキャストの機能を提供する web アプリケーションを作成する方法を示します。This tutorial shows how to create a web application that uses ASP.NET SignalR 2 to provide server broadcast functionality. サーバー ブロードキャストでは、サーバーがクライアントに送信される通信を開始することを意味します。Server broadcast means that the server starts the communications sent to clients.

このチュートリアルで作成するアプリケーションでは、株価情報、サーバー ブロードキャストの機能の一般的なシナリオをシミュレートします。The application that you'll create in this tutorial simulates a stock ticker, a typical scenario for server broadcast functionality. 定期的に、サーバーはランダムに株価を更新し、接続されているすべてのクライアントに、更新プログラムをブロードキャストします。Periodically, the server randomly updates stock prices and broadcast 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.

Web を作成します。

このチュートリアルでは、次の作業を行いました。In this tutorial, you:

  • プロジェクトの作成Create the project
  • サーバー コードを設定します。Set up the server code
  • サーバー コードを調べるExamine the server code
  • クライアント コードを設定します。Set up the client code
  • クライアント コードを調べるExamine the client code
  • アプリケーションをテストするTest the application
  • ログの有効化Enable logging

Important

アプリケーションの構築の手順を実行しない場合は、新しい空の ASP.NET Web アプリケーション プロジェクトで SignalR.Sample パッケージをインストールできます。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. このチュートリアルの手順を実行せず、NuGet パッケージをインストールした場合の手順に従ってください必要があります、 readme.txtファイル。If you install the NuGet package without performing the steps in this tutorial, you must follow the instructions in the readme.txt file. OWIN startup を追加する必要があるパッケージを実行するには、クラスの呼び出し、ConfigureSignalRインストールされたパッケージ内のメソッド。To run the package you need to add an OWIN startup class which calls the ConfigureSignalR method in the installed package. OWIN startup クラスを追加しない場合、エラーが表示されます。You will receive an error if you do not add the OWIN startup class. 参照してください、 StockTicker のサンプルをインストールこの記事の「します。See the Install the StockTicker sample section of this article.

必須コンポーネントPrerequisites

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

このセクションでは、Visual Studio 2017 を使用して、空の ASP.NET Web アプリケーションを作成する方法を示します。This section shows how to use Visual Studio 2017 to create an empty ASP.NET Web Application.

  1. Visual Studio で ASP.NET Web アプリケーションを作成します。In Visual Studio, create an ASP.NET Web Application.

    Web を作成します。

  2. 新しい ASP.NET Web アプリケーション - SignalR.StockTicker ウィンドウのままにを選択し、選択OKIn the New ASP.NET Web Application - SignalR.StockTicker window, leave Empty selected and select OK.

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

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

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

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

  1. ソリューション エクスプ ローラープロジェクトを右クリックし、選択、追加 > クラスします。In Solution Explorer, right-click the project and select Add > Class.

  2. クラスの名前Stockし、プロジェクトに追加します。Name the class Stock and add it to the project.

  3. コードに置き換えます、 Stock.csこのコード ファイル。Replace the code in the Stock.cs file with this 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 つのプロパティはSymbol(たとえば、Microsoft の MSFT) とPriceします。The two properties that you'll set when you create stocks are Symbol (for example, MSFT for Microsoft) and Price. その他のプロパティが設定する方法とタイミングに依存Priceします。The other properties depend on how and when you set Price. 初めて設定するPriceに、値が伝達されるDayOpenします。The first time you set Price, the value gets propagated to DayOpen. その後、設定するとPrice、アプリを計算、ChangePercentChangeプロパティ値の差に基づいてPriceDayOpenします。After that, when you set Price, the app calculates the Change and PercentChange property values based on the difference between Price and DayOpen.

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

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

StockTicker からブロードキャスト

1 つのインスタンスが欲しい、StockTickerそれぞれからの参照を設定する必要がありますので、サーバー上で実行するにはクラスStockTickerHubシングルトン インスタンスStockTickerインスタンス。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されていない、Hubクラス。The StockTicker class has to broadcast to clients because it has the stock data and triggers updates, but StockTicker isn't a Hub class. StockTickerクラスは、SignalR ハブの接続コンテキスト オブジェクトへの参照を取得する必要があります。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.

StockTickerHub.cs を作成します。Create StockTickerHub.cs

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

  2. 新しい項目の追加 - SignalR.StockTickerインストール済み > Visual C# > Web > SignalR選びSignalR ハブ クラス (v2) します。In Add New Item - SignalR.StockTicker, select Installed > Visual C# > Web > SignalR and then select SignalR Hub Class (v2).

  3. クラスの名前StockTickerHubし、プロジェクトに追加します。Name the class StockTickerHub and add it to the project.

    この手順で作成、 StockTickerHub.csクラス ファイル。This step creates the StockTickerHub.cs class file. 同時に、プロジェクトに SignalR をサポートする一連のスクリプト ファイルとアセンブリ参照を追加します。Simultaneously, it adds a set of script files and assembly references that supports SignalR to the project.

  4. コードに置き換えます、 StockTickerHub.csこのコード ファイル。Replace the code in the StockTickerHub.cs file with this code:

    using System.Collections.Generic;
    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();
            }
        }
    }
    
  5. ファイルを保存します。Save the file.

アプリでは、ハブメソッドは、クライアントは、サーバー上で呼び出すことができますを定義するクラス。The app uses the Hub class to define methods the clients can call on the server. 1 つのメソッドを定義する:GetAllStocks()します。You're 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 run synchronously and return IEnumerable<Stock> because it's returning data from memory.

指定したかどうか、メソッドがデータベース検索など、web サービス呼び出しの待機を含むは何かの手順を実行してデータを取得する必要があるTask<IEnumerable<Stock>>非同期処理を有効にする戻り値として。If the method had to get the data by doing something that would involve waiting, like 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 app will reference the Hub in JavaScript code on the client. クライアントに既定の名前は、この属性を使用しない場合は、例ではこのクラスの名前のキャメル ケース バージョンstockTickerHubします。The default name on the client if you don't use this attribute, is a camelCase version of the class name, which in this case would be stockTickerHub.

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

StockTicker.cs を作成します。Create StockTicker.cs

  1. ソリューション エクスプ ローラープロジェクトを右クリックし、選択、追加 > クラスします。In Solution Explorer, right-click the project and select Add > Class.

  2. クラスの名前StockTickerし、プロジェクトに追加します。Name the class StockTicker and add it to the project.

  3. コードに置き換えます、 StockTicker.csこのコード ファイル。Replace the code in the StockTicker.cs file with this 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<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 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 all threads will be running the same instance of StockTicker code, the StockTicker class has to be thread-safe.

サーバー コードを調べるExamine the server code

サーバー コードを確認する場合に役立つアプリの動作を理解します。If you examine the server code, it will help you understand how the app works.

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

静的な初期化_instanceをバックするフィールド、Instanceクラスのインスタンスのプロパティ。The code initializes the static _instance field that backs the Instance property with an instance of the class. コンス トラクターはプライベートなので、アプリを作成できるクラスの唯一のインスタンスになります。Because the constructor is private, it's the only instance of the class that the app can create. アプリは遅延初期化_instanceフィールド。The app uses Lazy initialization for the _instance field. パフォーマンス上の理由はありません。It's not for performance reasons. インスタンスの作成はスレッド セーフであるかどうかを確認するになります。It's to make sure the instance creation is thread-safe.

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 クラスの新しいインスタンスがから StockTicker のシングルトン インスタンスを取得する、StockTicker.Instanceの静的プロパティを見た前に、StockTickerHubクラス。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

コンス トラクターによって初期化、_stocksをサンプルの株価データ コレクションとGetAllStocks株式を返します。The constructor initializes the _stocks collection with some sample stock data, and GetAllStocks returns the stocks. 既に説明したよう株式のこのコレクションがによって返されるStockTickerHub.GetAllStocks、メソッドは、サーバーで、Hubクライアントが呼び出すことができるクラス。As you saw earlier, this collection of stocks is 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<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 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 app disposes of the StockTicker instance. 実際のアプリケーションでは、データベースのようなバックエンド データ ストアと動作します。In a real application, you would work with a back-end data store like a database.

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

コンス トラクターは、の起動時、Timerを定期的にランダムな単位で株価を更新するメソッドを呼び出すオブジェクト。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;
}

Timer 呼び出しUpdateStockPrices、state パラメーターで null を渡します。Timer calls UpdateStockPrices, which passes in null in the state parameter. 価格を更新する前に、アプリは、ロック取得、_updateStockPricesLockオブジェクト。Before updating prices, the app takes a lock 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 changes, the app calls BroadcastStockPrice to broadcast the stock price change to all connected clients.

_updatingStockPricesフラグが指定されている揮発性はスレッド セーフであるかどうかを確認します。The _updatingStockPrices flag designated volatile to make sure it is thread-safe.

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, the app 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, it's the object that needs to call an updateStockPrice method on all connected clients. Hubクラス、クライアントのメソッドを呼び出すための API は用意したが、StockTickerから派生していない、Hubクラスし、への参照がありません。Hubオブジェクト。In a Hub class, you have an API for calling client methods, but StockTicker doesn't derive from the Hub class and doesn't have a reference to any Hub object. 接続されているクライアントは、ブロードキャスト、StockTickerクラスの SignalR コンテキスト インスタンスを取得するには、StockTickerHubクラスし、クライアントでメソッドの呼び出しに使用します。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 コンテキストへの参照を取得し、コンス トラクター内に配置、Clientsプロパティ。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 回だけ取得する理由: コンテキストの取得は、高価なタスクでありを指定すると、アプリで、クライアントに送信されるメッセージの目的の順序を維持すると、それを取得します。There are two reasons why you want to get the context only once: getting the context is an expensive task, and getting it once makes sure the app preserves the intended order of messages sent to the clients.

private readonly static Lazy<StockTicker> _instance =
    new Lazy<StockTicker>(() => new StockTicker(GlobalHost.ConnectionManager.GetHubContext<StockTickerHub>().Clients));

private StockTicker(IHubConnectionContext<dynamic> clients)
{
    Clients = clients;

    // Remainder of constructor ...
}

private IHubConnectionContext<dynamic> Clients
{
    get;
    set;
}

private void BroadcastStockPrice(Stock stock)
{
    Clients.All.updateStockPrice(stock);
}

取得、Clientsプロパティのコンテキストと基本的には、StockTickerClientプロパティでは、クライアント メソッドを呼び出すコードの場合と同様、同じ外観を記述することができます、Hubクラス。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).

updateStockPriceで呼び出しているメソッドBroadcastStockPriceがまだ存在しません。The updateStockPrice method that you're calling in BroadcastStockPrice doesn't exist yet. 後で追加するクライアントで実行されるコードを記述するときにします。You'll add it later when you write code that runs on the client. 参照することができますupdateStockPriceここためClients.Allは動的で、アプリが実行時に式を評価することを意味します。You can refer to updateStockPrice here because Clients.All is dynamic, which means the app will evaluate the expression 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, the app will call that method and pass the parameter value 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. そのためには、OWIN startup クラスを追加します。To do that, add an OWIN startup class:

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

  2. 新しい項目の追加 - SignalR.StockTicker選択インストール済み > Visual C# > Webと選びOWIN Startup クラスします。In Add New Item - SignalR.StockTicker select Installed > Visual C# > Web and then select OWIN Startup Class.

  3. クラスの名前スタートアップ選択とOKします。Name the class Startup and select OK.

  4. 既定のコードを置き換える、 Startup.csこのコード ファイル。Replace the default code in the Startup.cs file with this code:

    using System;
    using System.Threading.Tasks;
    using Microsoft.Owin;
    using Owin;
    
    [assembly: OwinStartup(typeof(SignalR.StockTicker.Startup))]
    
    namespace SignalR.StockTicker
    {
        public class Startup
        {
            public void Configuration(IAppBuilder app)
            {
                // Any connection or hub wire up and configuration should go here
                app.MapSignalR();
            }
    
        }
    }
    

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

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

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

ページの HTML と JavaScript ファイルを作成します。Create the HTML page and JavaScript file

データを HTML ページが表示され、JavaScript ファイルは、データを整理します。The HTML page will display the data and the JavaScript file will organize the data.

StockTicker.html を作成します。Create StockTicker.html

まず、HTML クライアントを追加します。First, you'll add the HTML client.

  1. ソリューション エクスプ ローラープロジェクトを右クリックし、選択、追加 > HTML ページします。In Solution Explorer, right-click the project and select Add > HTML Page.

  2. ファイルに名前をStockTicker選択とOKします。Name the file StockTicker and select OK.

  3. 既定のコードを置き換える、 StockTicker.htmlこのコード ファイル。Replace the default code in the StockTicker.html file with this 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.10.2.min.js" ></script>
        <!--Reference the SignalR library. -->
        <script src="/Scripts/jquery.signalR-2.1.0.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 つの列にまたがる 1 つのセルを持つデータ行とテーブルを作成します。The HTML creates a table with five columns, a header row, and a data row with a single cell that spans all five columns. 「読み込み中...」アプリの起動時に一時的にデータ行を示しています。The data row shows "loading..." momentarily when the app starts. JavaScript コードはその行を削除して、サーバーから取得した株価データでその場所の行に追加します。JavaScript code will remove that row and add in its place rows with stock data retrieved from the server.

    スクリプト タグを指定します。The script tags specify:

    • JQuery スクリプト ファイル。The jQuery script file.

    • SignalR コア スクリプト ファイル。The SignalR core script file.

    • SignalR プロキシ スクリプト ファイルです。The SignalR proxies script file.

    • 後で作成する StockTicker スクリプト ファイル。A StockTicker script file that you'll create later.

    アプリは、SignalR プロキシ スクリプト ファイルを動的に生成されます。The app dynamically generates the SignalR proxies script file. 「/Signalr ハブ」の URL を指定し、Hub クラスは、ここでは、上のメソッドをプロキシのメソッドを定義します。、StockTickerHub.GetAllStocksします。It specifies the "/signalr/hubs" URL and defines proxy methods for the methods on the Hub class, in this case, for StockTickerHub.GetAllStocks. 使用してこの JavaScript ファイルが手動で生成できる場合は、 SignalR ユーティリティします。If you prefer, you can generate this JavaScript file manually by using SignalR Utilities. 動的ファイルの作成を無効にすることを忘れないでください、MapHubsメソッドの呼び出し。Don't forget to disable dynamic file creation in the MapHubs method call.

  4. ソリューション エクスプ ローラー、展開スクリプトします。In Solution Explorer, expand Scripts.

    JQuery と SignalR 用のスクリプト ライブラリは、プロジェクトに表示されます。Script libraries for jQuery and SignalR are visible in the project.

    Important

    パッケージ マネージャーは、以降のバージョンの SignalR スクリプトでインストールされます。The package manager will install a later version of the SignalR scripts.

  5. プロジェクト内のスクリプト ファイルのバージョンに対応するコード ブロック内のスクリプト参照を更新します。Update the script references in the code block to correspond to the versions of the script files in the project.

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

StockTicker.js を作成します。Create StockTicker.js

JavaScript ファイルを作成します。Now create the JavaScript file.

  1. ソリューション エクスプ ローラープロジェクトを右クリックし、選択、追加 > JavaScript ファイルします。In Solution Explorer, right-click the project and select Add > JavaScript File.

  2. ファイルに名前をStockTicker選択とOKします。Name the file StockTicker and select OK.

  3. このコードを追加、 StockTicker.jsファイル。Add this code to the StockTicker.js file:

    // 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);
    
    });
    

クライアント コードを調べるExamine the client code

クライアント コードを確認する場合に役立つクライアント コードがアプリケーションを動作させるサーバー コードと対話する方法について説明します。If you examine the client code, it will help you learn how the client code interacts with the server code to make the app work.

接続の開始Starting the connection

$.connection SignalR プロキシを参照します。$.connection refers to the SignalR proxies. コードのプロキシへの参照を取得する、StockTickerHubクラスし、内に配置、ticker変数。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 を呼び出すことによって、ファイル内のコードの最後の行が SignalR 接続を初期化しますすべての変数と関数を定義した後start関数。After you define all the variables and functions, 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. アプリケーションが非同期のアクションが完了したときに呼び出す関数を指定する元に戻す関数を呼び出すことができます。You can call the done function to specify the function to call when the app finishes the asynchronous action.

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

すべての素材を取得します。Getting all the stocks

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 形式で表記するサーバーの場合でも、クライアントにキャメル ケースを使用することを確認します。Notice that, by default, you have to use camelCasing on the client even though the method name is pascal-cased on the server. キャメル ケースのルールは、オブジェクトではなく、メソッドにのみ適用されます。The camelCasing rule only applies to methods, not objects. たとえばを参照してくださいstock.Symbolstock.Priceではなく、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();
}

initメソッドでは、アプリで、呼び出すことによって、サーバーから受信した各株オブジェクトのテーブル行に HTML が作成されますformatStockの書式設定のプロパティをstockオブジェクトし、を呼び出したsupplant内のプレースホルダーを置換するにはrowTemplate変数で、stockオブジェクト プロパティの値。In the init method, the app creates HTML for a table row for each stock object received from the server by calling formatStock to format properties of the stock object, and then by calling supplant to replace placeholders in the rowTemplate variable with the stock object property values. 結果の HTML は、株価のテーブルに追加されます。The resulting HTML is then appended to the stock table.

Note

呼び出すinitとしてそれに渡すことによって、callback後非同期に実行される関数start関数が完了するとします。You call init by passing it in as a callback function that executes after the asynchronous start function finishes. 呼び出した場合init呼び出した後、別の JavaScript ステートメントとしてstart、完了、接続を確立するのには start 関数を待たずにすぐに実行があるため、関数は失敗します。If you called init as a separate JavaScript statement after calling start, the function would fail because it would run 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 app establishes a server connection.

更新の株価の取得Getting updated stock prices

呼び出すサーバー株の価格が変更されたとき、updateStockPrice接続されているクライアントにします。When the server changes a stock's price, it calls the updateStockPrice on connected clients. アプリのクライアントのプロパティに関数を追加する、stockTicker使用できるようにする呼び出しをサーバーからのプロキシ。The app adds the function to the client property of the stockTicker proxy 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. テーブルに行を追加することではなく、テーブル内の株式の現在の行を検索し、その行を新しいに置き換えます。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

確認するためのアプリをテストすることができますが動作します。You can test the app to make sure it's working. 株価の変動をライブの株価のテーブルを表示するすべてのブラウザー ウィンドウが表示されます。You'll see all browser windows display the live stock table with stock prices fluctuating.

  1. ツールバーで、有効にするスクリプトのデバッグしデバッグ モードでアプリを実行する [再生] ボタンを選択します。In the toolbar, turn on Script Debugging and then select the play button to run the app in Debug mode.

    ユーザー モードをデバッグし、[再生] を選択のスクリーン ショット。

    表示するブラウザー ウィンドウが開き、在庫表の Liveします。A browser window will open displaying the Live Stock Table. ストックの表に、最初に行が示されます「読み込み中...」、その後、しばらくすると、アプリは、初期の株価データを表示し、株価を起動して変更します。The stock table initially shows the "loading..." line, then, after a short time, the app shows the initial stock data, and then the stock prices start to change.

  2. ブラウザーから URL をコピーし、他の 2 つのブラウザーを開き、アドレス バーに Url を貼り付けます。Copy the URL from the browser, open two other browsers, and paste the URLs into the address bars.

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

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

    StockTicker シングルトン オブジェクトは、サーバーで実行する継続します。The StockTicker singleton object continued to run in the server. 在庫表の Live株式が変更し続けていることを示しています。The Live Stock Table 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.

  2. ファイルの最後に、接続を初期化するコードの直前のログ記録を有効にするコードの強調表示された行を追加します。Add this highlighted 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);
    
  3. F5 キーを押してプロジェクトを実行します。Press F5 to run the project.

  4. ブラウザーの開発者ツール ウィンドウを開きし、ログを表示するコンソールを選択します。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're running Internet Explorer 10 on Windows 8 (IIS 8), the transport method is WebSockets.

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

    • Windows 8 (IIS 8) で Firefox 19 を実行している場合、トランスポート メソッドがWebsocketします。If you're running Firefox 19 on Windows 8 (IIS 8), the transport method is WebSockets.

      Tip

      Firefox の場合、コンソール ウィンドウを取得する Firebug アドインのインストールします。In Firefox, install the Firebug add-in to get a Console window.

    • Windows 7 (IIS 7.5) で Firefox 19 を実行している場合、トランスポート メソッドがサーバーによって送信されるイベント。If you're running Firefox 19 on Windows 7 (IIS 7.5), the transport method is server-sent events.

StockTicker サンプルをインストールします。Install the StockTicker sample

Microsoft.AspNet.SignalR.Sample StockTicker アプリケーションをインストールします。The Microsoft.AspNet.SignalR.Sample installs the StockTicker application. NuGet パッケージには、ゼロから作成された簡略化されたバージョンより多くの機能が含まれています。The NuGet package includes more features than the simplified version that you 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.

Important

このチュートリアルの前の手順を実行せず、パッケージをインストールする場合は、プロジェクトに OWIN startup クラスを追加する必要があります。If you install the package without performing the earlier steps of this tutorial, you must add an OWIN startup class to your project. NuGet パッケージの場合は、この readme.txt ファイルには、この手順について説明します。This readme.txt file for the NuGet package explains this step.

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

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

  2. NuGet パッケージ マネージャー。SignalR.StockTicker参照します。In NuGet Package manager: SignalR.StockTicker, select Browse.

  3. パッケージ ソースnuget.orgします。From Package source, select nuget.org.

  4. 入力SignalR.Sample検索ボックスを選びMicrosoft.AspNet.SignalR.Sample > インストールします。Enter SignalR.Sample in the search box and select Microsoft.AspNet.SignalR.Sample > Install.

  5. ソリューション エクスプ ローラー、展開、 SignalR.Sampleフォルダー。In Solution Explorer, expand the SignalR.Sample folder.

    SignalR.Sample パッケージをインストールすると、フォルダーとその内容が作成されます。Installing the SignalR.Sample package created the folder and its contents.

  6. SignalR.Sampleフォルダーを右クリックしてStockTicker.html、し、スタート ページとして設定します。In the SignalR.Sample folder, right-click StockTicker.html, and then select 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

初めてのアプリで紹介したテーブルには、便利な機能が必要があります。The table that you saw in the first app had useful features. 完全な株価表示器のアプリケーションの新機能を示しています。 株価データおよび増加し、分類の色を変更する株価を表示するウィンドウを水平方向にスクロールします。The full stock ticker application shows new features: a horizontally scrolling window that shows the stock data and stocks that change color as they rise and fall.

  1. F5 キーを押してアプリを実行します。Press F5 to run the app.

    初めてアプリを実行して、「市場」は"closed"静的なテーブルとティッカー ウィンドウ スクロールはありませんを参照してください。When you run the app for the first time, the "market" is "closed" and you see a static table and a ticker window that isn't scrolling.

  2. 選択Open Marketします。Select Open Market.

    ライブ ティッカーのスクリーン ショット。

    • 株式ティッカーの Liveを水平方向にスクロール ボックスを起動し、サーバーがランダムに株価の変更を定期的にブロードキャストする開始します。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, the app updates both the Live Stock Table and the Live Stock Ticker.

    • 株式の価格の変更は、正の値は、アプリには、背景が緑の在庫が表示されます。When a stock's price change is positive, the app shows the stock with a green background.

    • 変更が負の値と、アプリには、背景が赤の素材が表示されます。When the change is negative, the app shows the stock with a red background.

  3. 選択市場を閉じるします。Select Close Market.

    • 表に、更新が停止します。The table updates stop.

    • スクロール、ティッカーを停止します。The ticker stops scrolling.

  4. 選択リセットします。Select Reset.

    • すべての株価データはリセットされます。All stock data is reset.

    • アプリでは、料金の変更を開始する前に初期状態を復元します。The app restores the initial state before price changes started.

  5. ブラウザーから URL をコピーし、他の 2 つのブラウザーを開き、アドレス バーに Url を貼り付けます。Copy the URL from the browser, open two other browsers, and paste the URLs into the address bars.

  6. 各ブラウザーで同時に動的に更新される同じデータを表示します。You see the same data dynamically updated at the same time in each browser.

  7. コントロールのいずれかを選択するとすべてのブラウザーと同じ方法を同時に応答します。When you select any of the controls, all browsers respond the same way at the same time.

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

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

SignalR.Sample StockTicker.htmlSignalR.Sample StockTicker.html

株価情報の HTML コード:The stock ticker HTML code:

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

SignalR.Sample StockTicker.cssSignalR.Sample StockTicker.css

株式ティッカーの CSS コード:The stock ticker CSS code:

#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;
    }

SignalR.Sample SignalR.StockTicker.jsSignalR.Sample SignalR.StockTicker.js

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

アプリに柔軟性を追加するには、追加のメソッドが、アプリが呼び出すことができます。To add flexibility to the app, there are additional methods the app can call.

SignalR.Sample StockTickerHub.csSignalR.Sample StockTickerHub.cs

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();
}

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

SignalR.Sample StockTicker.csSignalR.Sample StockTicker.cs

StockTickerクラス、アプリは、市場の状態を保持、MarketStateを返すプロパティをMarketState列挙値。In the StockTicker class, the app maintains the state of the market with 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 thread-safe:

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 make sure this code is thread-safe, the _marketState field that backs the MarketState property designated volatile:

private volatile MarketState _marketState;

BroadcastMarketStateChangeBroadcastMarketResetメソッドは、クライアントで定義されている別のメソッドを呼び出す点を除いて、既に説明しましたが 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 table 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. これらも停止または開始、株式ティッカーの Live水平方向にスクロールします。They also stop or start the Live Stock Ticker horizontal scrolling. 多くの関数に追加されているためticker.client、アプリでは、 jQuery 関数を拡張するに追加します。Since many functions are being added to ticker.client, the app uses the jQuery extend function 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

クライアント接続を確立した後、追加の作業を行うがあります。After the client establishes the connection, it has some additional work to do:

  • 市場が開いているか、適切な呼び出しを閉じてとかどうかmarketOpenedまたはmarketClosed関数。Find out if the market is open or closed to call the appropriate marketOpened or marketClosed function.

  • ボタンにサーバー メソッドの呼び出しをアタッチします。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 aren't wired up to the buttons until after the app establishes the connection. これは、コードが利用可能になる前にサーバーのメソッドを呼び出すことはできませんのでです。It's so the code can't call the server methods before they're available.

その他の技術情報Additional resources

このチュートリアルでは、接続されているすべてのクライアントをサーバーからメッセージをブロードキャストする SignalR アプリケーションをプログラミングする方法を学習できました。In this tutorial you've learned how to program a SignalR application that broadcasts messages from the server to all connected clients. ここで任意のクライアントからの通知に応答して定期的にメッセージをブロードキャストすることができます。Now you can broadcast messages on a periodic basis and in response to notifications from any client. マルチ スレッドのシングルトン インスタンスの概念は、マルチ プレーヤー オンライン ゲーム シナリオでサーバーの状態を維持するために使用できます。You can use the concept of multi-threaded singleton instance to maintain server state in multi-player online game scenarios. 例については、次を参照してください。 SignalR に基づいて ShootR ゲームします。For an example, see the ShootR game 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 は、次のリソースを参照してください。For more about SignalR, see the following resources:

次の手順Next steps

このチュートリアルでは、次の作業を行いました。In this tutorial, you:

  • プロジェクトの作成Created the project
  • サーバー コードを設定します。Set up the server code
  • サーバー コードを調べるExamined the server code
  • クライアント コードを設定します。Set up the client code
  • クライアント コードを調べるExamined the client code
  • アプリケーションのテストTested the application
  • ログ記録を有効になっています。Enabled logging

ASP.NET SignalR 2 を使用するリアルタイムの web アプリケーションを作成する方法については、次の記事に進んでください。Advance to the next article to learn how to create a real-time web application that uses ASP.NET SignalR 2.