ASP.NET Core SignalR .NET クライアントASP.NET Core SignalR .NET Client

ASP.NET Core SignalR .NET クライアント ライブラリでは、.NET アプリからの SignalR ハブと通信できます。The ASP.NET Core SignalR .NET client library lets you communicate with SignalR hubs from .NET apps.

サンプル コードを表示またはダウンロードします (ダウンロード方法)。View or download sample code (how to download)

この記事のサンプル コードは、ASP.NET Core SignalR .NET クライアントを使用する WPF アプリです。The code sample in this article is a WPF app that uses the ASP.NET Core SignalR .NET client.

SignalR .NET クライアント パッケージをインストールします。Install the SignalR .NET client package

Microsoft.AspNetCore.SignalR.Client SignalR ハブに接続するための .NET クライアント パッケージが必要です。The Microsoft.AspNetCore.SignalR.Client package is needed for .NET clients to connect to SignalR hubs. クライアント ライブラリをインストールする、次のコマンドを実行、パッケージ マネージャー コンソールウィンドウ。To install the client library, run the following command in the Package Manager Console window:

Install-Package Microsoft.AspNetCore.SignalR.Client

ハブへの接続します。Connect to a hub

接続を確立するには、作成、HubConnectionBuilderを呼び出すとBuildします。To establish a connection, create a HubConnectionBuilder and call Build. 接続の作成中には、ハブの URL、プロトコル、トランスポートの種類、ログ レベル、ヘッダー、およびその他のオプションを構成できます。The hub URL, protocol, transport type, log level, headers, and other options can be configured while building a connection. 挿入することで、必要なオプションを構成、HubConnectionBuilderメソッドにBuildします。Configure any required options by inserting any of the HubConnectionBuilder methods into Build. 接続を開始StartAsyncします。Start the connection with StartAsync.

using System;
using System.Threading.Tasks;
using System.Windows;
using Microsoft.AspNetCore.SignalR.Client;

namespace SignalRChatClient
{
    public partial class MainWindow : Window
    {
        HubConnection connection;
        public MainWindow()
        {
            InitializeComponent();

            connection = new HubConnectionBuilder()
                .WithUrl("http://localhost:53353/ChatHub")
                .Build();

            connection.Closed += async (error) =>
            {
                await Task.Delay(new Random().Next(0,5) * 1000);
                await connection.StartAsync();
            };
        }

        private async void connectButton_Click(object sender, RoutedEventArgs e)
        {
            connection.On<string, string>("ReceiveMessage", (user, message) =>
            {
                this.Dispatcher.Invoke(() =>
                {
                   var newMessage = $"{user}: {message}";
                   messagesList.Items.Add(newMessage);
                });
            });

            try
            {
                await connection.StartAsync();
                messagesList.Items.Add("Connection started");
                connectButton.IsEnabled = false;
                sendButton.IsEnabled = true;
            }
            catch (Exception ex)
            {
                messagesList.Items.Add(ex.Message);
            }
        }

        private async void sendButton_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                await connection.InvokeAsync("SendMessage", 
                    userTextBox.Text, messageTextBox.Text);
            }
            catch (Exception ex)
            {                
                messagesList.Items.Add(ex.Message);                
            }
        }
    }
}

接続が失われたハンドルHandle lost connection

自動的に再接続します。Automatically reconnect

HubConnectionを使用して自動的に再接続するように構成できる、WithAutomaticReconnectメソッドをHubConnectionBuilderします。The HubConnection can be configured to automatically reconnect using the WithAutomaticReconnect method on the HubConnectionBuilder. 既定では、自動的に再接続しません。It won't automatically reconnect by default.

HubConnection connection= new HubConnectionBuilder()
    .WithUrl(new Uri("http://127.0.0.1:5000/chatHub"))
    .WithAutomaticReconnect()
    .Build();

任意のパラメーターを指定せずWithAutomaticReconnect()後、4 つの失敗した試行を停止する各再接続の試行を試す前に、それぞれ 0、2、10、および 30 秒間待機するクライアントを構成します。Without any parameters, WithAutomaticReconnect() configures the client to wait 0, 2, 10, and 30 seconds respectively before trying each reconnect attempt, stopping after four failed attempts.

任意の再接続試行を開始する前に、HubConnectionへの移行には、HubConnectionState.Reconnecting状態にあり、起動、Reconnectingイベント。Before starting any reconnect attempts, the HubConnection will transition to the HubConnectionState.Reconnecting state and fire the Reconnecting event. これは、UI 要素を無効にして、接続が失われたことをユーザーに警告する機会を提供します。This provides an opportunity to warn users that the connection has been lost and to disable UI elements. 非対話型のアプリには、キューまたはメッセージのドロップを開始できます。Non-interactive apps can start queuing or dropping messages.

connection.Reconnecting += error =>
{
    Debug.Assert(connection.State == HubConnectionState.Reconnecting);

    // Notify users the connection was lost and the client is reconnecting.
    // Start queuing or dropping messages.

    return Task.CompletedTask;
};

内の最初の 4 つの試行で、クライアントが再接続に成功した場合、HubConnectionから戻るへの移行、Connected状態にあり、起動、Reconnectedイベント。If the client successfully reconnects within its first four attempts, the HubConnection will transition back to the Connected state and fire the Reconnected event. これは、接続が再確立された、すべてのキューに置かれたメッセージをデキューするユーザーに通知する機会を提供します。This provides an opportunity to inform users the connection has been reestablished and dequeue any queued messages.

接続は、サーバーから完全に新規に見えるため、新しいConnectionIdに提供される、Reconnectedイベント ハンドラー。Since the connection looks entirely new to the server, a new ConnectionId will be provided to the Reconnected event handlers.

警告

Reconnectedイベント ハンドラーのconnectionIdパラメーターが null にする場合、HubConnectionするように構成されたネゴシエーションをスキップします。The Reconnected event handler's connectionId parameter will be null if the HubConnection was configured to skip negotiation.

connection.Reconnected += connectionId =>
{
    Debug.Assert(connection.State == HubConnectionState.Connected);

    // Notify users the connection was reestablished.
    // Start dequeuing messages queued while reconnecting if any.

    return Task.CompletedTask;
};

WithAutomaticReconnect() 構成はありません、HubConnection起動障害を手動で処理する必要があるために、初回起動時の障害を再試行します。WithAutomaticReconnect() won't configure the HubConnection to retry initial start failures, so start failures need to be handled manually:

public static async Task<bool> ConnectWithRetryAsync(HubConnection connection, CancellationToken token)
{
    // Keep trying to until we can start or the token is canceled.
    while (true)
    {
        try
        {
            await connection.StartAsync(token);
            Debug.Assert(connection.State == HubConnectionState.Connected);
            return true;
        }
        catch when (token.IsCancellationRequested)
        {
            return false;
        }
        catch
        {
            // Failed to connect, trying again in 5000 ms.
            Debug.Assert(connection.State == HubConnectionState.Disconnected);
            await Task.Delay(5000);
        }
    }
}

内の最初の 4 つの試行で、クライアントが再接続が正常に場合、HubConnectionへの移行には、Disconnected状態にあり、起動、Closedイベント。If the client doesn't successfully reconnect within its first four attempts, the HubConnection will transition to the Disconnected state and fire the Closed event. これは、接続を手動で再起動するか、接続が完全に失われたことをユーザーに通知しようとする機会を提供します。This provides an opportunity to attempt to restart the connection manually or inform users the connection has been permanently lost.

connection.Closed += error =>
{
    Debug.Assert(connection.State == HubConnectionState.Disconnected);

    // Notify users the connection has been closed or manually try to restart the connection.

    return Task.CompletedTask;
};

切断する前に再接続試行のカスタムの数を構成または再接続のタイミングを変更するにはWithAutomaticReconnect再接続が試みられるたびに開始する前に待機するミリ秒の遅延を表す数値の配列を受け入れます。In order to configure a custom number of reconnect attempts before disconnecting or change the reconnect timing, WithAutomaticReconnect accepts an array of numbers representing the delay in milliseconds to wait before starting each reconnect attempt.

HubConnection connection= new HubConnectionBuilder()
    .WithUrl(new Uri("http://127.0.0.1:5000/chatHub"))
    .WithAutomaticReconnect(new[] { TimeSpan.Zero, TimeSpan.Zero, TimeSpan.FromSeconds(10) })
    .Build();

    // .WithAutomaticReconnect(new[] { TimeSpan.Zero, TimeSpan.FromSeconds(2), TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(30) }) yields the default behavior.

上記の例では、HubConnection接続が失われた後にすぐに再接続しようとすると開始します。The preceding example configures the HubConnection to start attempting reconnects immediately after the connection is lost. またこれは、既定の構成に当てはまります。This is also true for the default configuration.

既定の構成でこれと同じように、2 秒待機しているのではなく、最初の再接続試行が失敗すると、2 回目の再接続試行がすぐに開始もは。If the first reconnect attempt fails, the second reconnect attempt will also start immediately instead of waiting 2 seconds like it would in the default configuration.

2 回目の再接続の試行が失敗した場合、これは、既定の構成と同様にもう一度、10 秒後に、3 番目の再接続の試行が開始されます。If the second reconnect attempt fails, the third reconnect attempt will start in 10 seconds which is again like the default configuration.

カスタム動作し、もう一度ブロックから分化既定の動作を 3 番目の再接続試行の失敗後に停止します。The custom behavior then diverges again from the default behavior by stopping after the third reconnect attempt failure. 既定の構成ではする 1 つより再接続別の 30 秒以内に試行します。In the default configuration there would be one more reconnect attempt in another 30 seconds.

タイミングと自動の数をさらに多くのコントロールの接続試行、ならWithAutomaticReconnect実装するオブジェクトを受け入れる、IRetryPolicyインターフェイスという単一のメソッドをNextRetryDelayします。If you want even more control over the timing and number of automatic reconnect attempts, WithAutomaticReconnect accepts an object implementing the IRetryPolicy interface, which has a single method named NextRetryDelay.

NextRetryDelay 型の 1 つの引数RetryContextします。NextRetryDelay takes a single argument with the type RetryContext. RetryContextは 3 つのプロパティがあります: PreviousRetryCountElapsedTimeRetryReasonである、 longTimeSpanExceptionそれぞれします。The RetryContext has three properties: PreviousRetryCount, ElapsedTime and RetryReason which are a long, a TimeSpan and an Exception respectively. 最初の再接続試行する前に両方PreviousRetryCountElapsedTimeゼロ、およびRetryReason接続が失われる原因となった例外になります。Before the first reconnect attempt, both PreviousRetryCount and ElapsedTime will be zero, and the RetryReason will be the Exception that caused the connection to be lost. 各障害が発生した再試行後PreviousRetryCount、1 つずつ増えますElapsedTimeが再接続をこれまでに費やされた時間数を反映するように更新されます、RetryReason最後に再接続試行失敗の原因となった例外になります。After each failed retry attempt, PreviousRetryCount will be incremented by one, ElapsedTime will be updated to reflect the amount of time spent reconnecting so far, and the RetryReason will be the Exception that caused the last reconnect attempt to fail.

NextRetryDelay いずれかを表す TimeSpan 時間待ってから、[次へ] の再接続の試行を返す必要がありますまたはnull場合、HubConnection再接続を停止する必要があります。NextRetryDelay must return either a TimeSpan representing the time to wait before the next reconnect attempt or null if the HubConnection should stop reconnecting.

public class RandomRetryPolicy : IRetryPolicy
{
    private readonly Random _random = new Random();

    public TimeSpan? NextRetryDelay(RetryContext retryContext)
    {
        // If we've been reconnecting for less than 60 seconds so far,
        // wait between 0 and 10 seconds before the next reconnect attempt.
        if (retryContext.ElapsedTime < TimeSpan.FromSeconds(60))
        {
            return TimeSpan.FromSeconds(_random.Next() * 10);
        }
        else
        {
            // If we've been reconnecting for more than 60 seconds so far, stop reconnecting.
            return null;
        }
    }
}
HubConnection connection = new HubConnectionBuilder()
    .WithUrl(new Uri("http://127.0.0.1:5000/chatHub"))
    .WithAutomaticReconnect(new RandomRetryPolicy())
    .Build();

再接続で示すように手動で、クライアント コードを記述する代わりに、手動で再接続します。Alternatively, you can write code that will reconnect your client manually as demonstrated in Manually reconnect.

手動での再接続します。Manually reconnect

警告

3.0 では、前に SignalR 用の .NET クライアントは自動的に再接続しません。Prior to 3.0, the .NET client for SignalR doesn't automatically reconnect. クライアントを手動で再接続するコードを記述する必要があります。You must write code that will reconnect your client manually.

使用して、Closed失われた接続に応答するイベントです。Use the Closed event to respond to a lost connection. たとえば、再接続を自動化することがあります。For example, you might want to automate reconnection.

Closedイベントを返すデリゲートが必要です、 Task、非同期コードを使用せずに実行することができますasync voidします。The Closed event requires a delegate that returns a Task, which allows async code to run without using async void. デリゲートのシグネチャを満たすために、Closedイベント ハンドラーの実行を同期的に、返すTask.CompletedTask:To satisfy the delegate signature in a Closed event handler that runs synchronously, return Task.CompletedTask:

connection.Closed += (error) => {
    // Do your close logic.
    return Task.CompletedTask;
};

非同期サポートの主な理由とは、接続を再起動するためです。The main reason for the async support is so you can restart the connection. 非同期アクションは、接続を開始します。Starting a connection is an async action.

Closedハンドラー、接続の再起動時は、次の例に示すように、サーバーのオーバー ロードを防ぐためにランダムな時間の待機を検討してください。In a Closed handler that restarts the connection, consider waiting for some random delay to prevent overloading the server, as shown in the following example:

connection.Closed += async (error) =>
{
    await Task.Delay(new Random().Next(0,5) * 1000);
    await connection.StartAsync();
};

クライアントからのハブ メソッドの呼び出しCall hub methods from client

InvokeAsync ハブのメソッドを呼び出します。InvokeAsync calls methods on the hub. ハブ メソッドの名前およびハブ メソッドで定義されている引数を渡すInvokeAsyncします。Pass the hub method name and any arguments defined in the hub method to InvokeAsync. SignalR が非同期でこれを使用して、asyncawait呼び出しを行うときにします。SignalR is asynchronous, so use async and await when making the calls.

await connection.InvokeAsync("SendMessage", 
    userTextBox.Text, messageTextBox.Text);

InvokeAsyncメソッドを返します。 をTaskサーバー メソッドが戻るときに完了します。The InvokeAsync method returns a Task which completes when the server method returns. 戻り値は、存在する場合の結果として提供されます、Taskします。The return value, if any, is provided as the result of the Task. サーバー上のメソッドによってスローされた例外を生成するエラーが発生したTaskします。Any exceptions thrown by the method on the server produce a faulted Task. 使用awaitサーバー メソッドが完了するまで待機するための構文とtry...catch構文エラーを処理します。Use await syntax to wait for the server method to complete and try...catch syntax to handle errors.

SendAsyncメソッドを返します。 をTaskメッセージがサーバーに送信されたときにこれが完了するとします。The SendAsync method returns a Task which completes when the message has been sent to the server. この戻り値が指定されていないTaskサーバー メソッドが完了するまで待機しません。No return value is provided since this Task doesn't wait until the server method completes. メッセージの送信中に、クライアントでスローされた例外を生成、エラーが発生したTaskします。Any exceptions thrown on the client while sending the message produce a faulted Task. 使用awaittry...catch処理するために構文エラーを送信します。Use await and try...catch syntax to handle send errors.

注意

Azure SignalR サービスを使用している場合サーバーレス モード、クライアントからハブ メソッドを呼び出すことはできません。If you're using Azure SignalR Service in Serverless mode, you cannot call hub methods from a client. 詳細については、次を参照してください。、 SignalR サービスのドキュメントします。For more information, see the SignalR Service documentation.

ハブからのクライアント メソッドを呼び出すCall client methods from hub

ハブ呼び出しを使用してメソッドを一切定義connection.Onしますが、接続を開始する前に、ビルド後にします。Define methods the hub calls using connection.On after building, but before starting the connection.

connection.On<string, string>("ReceiveMessage", (user, message) =>
{
    this.Dispatcher.Invoke(() =>
    {
       var newMessage = $"{user}: {message}";
       messagesList.Items.Add(newMessage);
    });
});

上記のコードでconnection.Onを使用してサーバー側コードから呼び出すときに実行される、SendAsyncメソッド。The preceding code in connection.On runs when server-side code calls it using the SendAsync method.

public async Task SendMessage(string user, string message)
{
    await Clients.All.SendAsync("ReceiveMessage", user,message);
}

エラー処理とログ記録Error handling and logging

Try-catch ステートメントでエラーを処理します。Handle errors with a try-catch statement. 検査、Exceptionエラーが発生した後に実行する適切なアクションを決定するオブジェクト。Inspect the Exception object to determine the proper action to take after an error occurs.

try
{
    await connection.InvokeAsync("SendMessage", 
        userTextBox.Text, messageTextBox.Text);
}
catch (Exception ex)
{                
    messagesList.Items.Add(ex.Message);                
}

その他の技術情報Additional resources