SignalRASP.NET Core .NET-Client

Mit der SignalR ASP.NET Core .NET-Clientbibliothek können Sie über SignalR .NET-Apps mit Hubs kommunizieren.

Anzeigen oder Herunterladen von Beispielcode (Vorgehensweise zum Herunterladen)

Das Codebeispiel in diesem Artikel ist eine WPF-App, die den ASP.NET Core SignalR .NET-Client verwendet.

Installieren des SignalR .NET-Clientpakets

Microsoft.AspNetCore. SignalR Das Clientpaket ist erforderlich, damit .NET-Clients eine Verbindung mit Hubs herstellen SignalR können.

Um die Clientbibliothek zu installieren, führen Sie den folgenden Befehl im Paket-Manager Konsolenfenster aus:

Install-Package Microsoft.AspNetCore.SignalR.Client

Verbinden zu einem Hub

Um eine Verbindung herzustellen, erstellen Sie einen HubConnectionBuilder , und rufen Sie Build auf. Die Hub-URL, das Protokoll, der Transporttyp, die Protokollebene, Header und andere Optionen können beim Erstellen einer Verbindung konfiguriert werden. Konfigurieren Sie alle erforderlichen Optionen, indem Sie eine der HubConnectionBuilder Methoden in Build einfügen. Starten Sie die Verbindung mit 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);                
            }
        }
    }
}

Behandeln verlorener Verbindungen

Automatisches Wiederherstellen der Verbindung

HubConnectionkann so konfiguriert werden, dass die Verbindung mithilfe der -Methode für automatisch wiederhergestellt WithAutomaticReconnect HubConnectionBuilder wird. Standardmäßig wird die Verbindung nicht automatisch wiederhergestellt.

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

Ohne Parameter WithAutomaticReconnect() konfiguriert den Client so, dass er 0, 2, 10 bzw. 30 Sekunden wartet, bevor jeder Verbindungsversuch versucht wird, und nach vier fehlgeschlagenen Versuchen beendet wird.

Bevor versucht wird, die Verbindung wiederherzustellen, wechselt in HubConnection den Zustand und löst das Ereignis HubConnectionState.Reconnecting Reconnecting aus. Dies bietet die Möglichkeit, Benutzer zu warnen, dass die Verbindung unterbrochen wurde, und Benutzeroberflächenelemente zu deaktivieren. Nicht interaktive Apps können mit dem Inwarteschlangen- oder Verwerfen von Nachrichten beginnen.

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

Wenn der Client innerhalb der ersten vier Versuche erfolgreich wieder eine Verbindung herstellen kann, wechselt zurück HubConnection in den Zustand und löst das Ereignis Connected Reconnected aus. Dies bietet die Möglichkeit, Benutzer darüber zu informieren, dass die Verbindung wiederhergestellt wurde, und nachrichten in der Warteschlange aus der Warteschlange zu löschen.

Da die Verbindung für den Server völlig neu aussieht, ConnectionId wird den Ereignishandlern eine neue Reconnected bereitgestellt.

Warnung

Der Reconnected -Parameter des Ereignishandlers connectionId ist NULL, wenn zum Überspringen der HubConnection Aushandlungkonfiguriert wurde.

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() wird nicht so HubConnection konfiguriert, dass anfängliche Startfehler wiederholt werden. Daher müssen Startfehler manuell behandelt werden:

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

Wenn der Client innerhalb der ersten vier Versuche nicht erfolgreich wieder eine Verbindung herstellen kann, wechselt in HubConnection den Zustand und löst das Ereignis Disconnected Closed aus. Dies bietet die Möglichkeit, die Verbindung manuell neu zu starten oder Benutzer darüber zu informieren, dass die Verbindung dauerhaft unterbrochen wurde.

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

Um eine benutzerdefinierte Anzahl von Verbindungsversuchen vor dem Trennen der Verbindung zu konfigurieren oder den Zeitpunkt der Erneutverbindung zu ändern, WithAutomaticReconnect akzeptiert ein Array von Zahlen, die die Verzögerung in Millisekunden darstellen, die gewartet werden soll, bevor jeder Verbindungsversuch gestartet wird.

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.

Im vorherigen Beispiel wird so konfiguriert, dass sofort nach dem HubConnection Verlust der Verbindung versucht wird, die Verbindung wiederherzustellen. Dies gilt auch für die Standardkonfiguration.

Wenn der erste Versuch der erneuten Verbindung fehlschlägt, wird der zweite Versuch zur erneuten Verbindung ebenfalls sofort gestartet, anstatt 2 Sekunden zu warten, wie es in der Standardkonfiguration der Falle wäre.

Wenn der zweite Verbindungsversuch fehlschlägt, wird der dritte Verbindungsversuch in 10 Sekunden gestartet, was wiederum der Standardkonfiguration entspricht.

Das benutzerdefinierte Verhalten weicht dann wieder vom Standardverhalten ab, indem es nach dem dritten Verbindungsversuchsfehler beendet wird. In der Standardkonfiguration gibt es in weiteren 30 Sekunden einen weiteren Verbindungsversuch.

Wenn Sie noch mehr Kontrolle über den Zeitlichen Ablauf und die Anzahl automatischer Verbindungsversuche wünschen, WithAutomaticReconnect akzeptiert ein Objekt, das die IRetryPolicy -Schnittstelle implementiert, die über eine einzelne Methode namens NextRetryDelay verfügt.

NextRetryDelay nimmt ein einzelnes Argument mit dem Typ RetryContext an. verfügt über RetryContext drei Eigenschaften: PreviousRetryCount und , die jeweils ein , ein und ein ElapsedTime RetryReason long TimeSpan Exception sind. Vor dem ersten Versuch, die Verbindung wiederherzustellen, sind sowohl als auch PreviousRetryCount ElapsedTime 0 (null), und ist RetryReason die Ausnahme, die dazu geführt hat, dass die Verbindung unterbrochen wurde. Nach jedem fehlgeschlagenen Wiederholungsversuch PreviousRetryCount wird um eins erhöht, aktualisiert, um die bisher aufgewendete Zeit für die ElapsedTime Wiederherstellung der Verbindung widerzuspiegeln, und ist RetryReason die Ausnahme, die dazu geführt hat, dass der letzte Verbindungsversuch fehlschlug.

NextRetryDelay muss entweder eine TimeSpan zurückgeben, die die Wartezeit vor dem nächsten Verbindungsversuch darstellt, oder null , wenn die verbindung beenden HubConnection soll.

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.NextDouble() * 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();

Alternativ können Sie Code schreiben, der den Client manuell erneut verbindet, wie unter Manuelles Wiederherstellen der Verbindunggezeigt.

Manuelles Wiederherstellen der Verbindung

Warnung

Vor 3.0 stellt der .NET-Client für SignalR nicht automatisch eine neue Verbindung her. Sie müssen Code schreiben, der den Client manuell erneut verbindet.

Verwenden Sie das Closed -Ereignis, um auf eine verlorene Verbindung zu reagieren. Es kann beispielsweise sein, dass Sie die erneute Verbindung automatisieren möchten.

Das Closed Ereignis erfordert einen Delegaten, der zurückgibt, wodurch Task asynchroner Code ohne Verwendung von ausgeführt werden async void kann. Um die Delegatsignatur in einem Closed synchron ausgeführten Ereignishandler zu erfüllen, geben Sie Task.CompletedTask zurück:

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

Der Hauptgrund für die asynchrone Unterstützung ist, dass Sie die Verbindung neu starten können. Das Starten einer Verbindung ist eine asynchrone Aktion.

Erwägen Sie in einem Closed Handler, der die Verbindung neu startet, auf eine zufällige Verzögerung zu warten, um eine Überladung des Servers zu verhindern, wie im folgenden Beispiel gezeigt:

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

Aufrufen von Hubmethoden vom Client

InvokeAsync ruft Methoden auf dem Hub auf. Übergeben Sie den Namen der Hubmethode und alle in der Hubmethode definierten Argumente an InvokeAsync . SignalR ist asynchron. Verwenden Sie daher async und , wenn Sie die await Aufrufe vornehmen.

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

Die InvokeAsync -Methode gibt einen Task zurück, der abgeschlossen wird, wenn die Servermethode zurückgegeben wird. Der Rückgabewert ,sofern vorhanden, wird als Ergebnis der Task bereitgestellt. Alle Ausnahmen, die von der -Methode auf dem Server ausgelöst werden, erzeugen einen fehlerhaften Task . Verwenden Sie await die -Syntax, um auf den Abschluss der Servermethode und try...catch die Syntax zum Behandeln von Fehlern zu warten.

Die SendAsync -Methode gibt einen Task zurück, der abgeschlossen wird, wenn die Nachricht an den Server gesendet wurde. Es wird kein Rückgabewert bereitgestellt, da Task dies nicht wartet, bis die Servermethode abgeschlossen ist. Alle Ausnahmen, die beim Senden der Nachricht auf dem Client ausgelöst werden, erzeugen einen fehlerhaften Task . Verwenden Sie await die Syntax und , um try...catch Sendefehler zu behandeln.

Hinweis

Das Aufrufen von Hubmethoden von einem Client wird nur unterstützt, wenn der SignalR Azure-Dienst im Standardmodus verwendet wird. Weitere Informationen finden Sie unter Häufig gestellte Fragen (azure-signalr GitHub Repository).

Aufrufen von Clientmethoden über den Hub

Definieren Sie Methoden, die der Hub nach dem connection.On Erstellen, aber vor dem Starten der Verbindung aufruft.

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

Der vorangehende Code in connection.On wird ausgeführt, wenn serverseitiger Code ihn mithilfe der SendAsync -Methode aufruft.

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

Fehlerbehandlung und Protokollierung

Behandeln von Fehlern mit einer try-catch-Anweisung. Überprüfen Sie das Exception -Objekt, um die richtige Aktion zu bestimmen, die nach einem Fehler ausgeführt werden soll.

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

Zusätzliche Ressourcen