Delen via


ASP.NET Core SignalR .NET client

Met de ASP.NET Core SignalR .NET-clientbibliotheek kunt u communiceren met SignalR hubs vanuit .NET-apps.

Voorbeeldcode bekijken of downloaden (hoe download je)

Het codevoorbeeld in dit artikel is een WPF-app die gebruikmaakt van de ASP.NET Core SignalR .NET-client.

SignalR Het .NET-clientpakket installeren

Microsoft.AspNetCore.SignalR. Clientpakket is vereist voor .NET-clients om verbinding te SignalR maken met hubs.

Als u de clientbibliotheek wilt installeren, voert u de volgende opdracht uit in het venster Package Manager Console :

Install-Package Microsoft.AspNetCore.SignalR.Client

Verbinding maken met een hub

Om een verbinding tot stand te brengen, maakt u een HubConnectionBuilder en roept u Build aan. De hub-URL, het protocol, het transporttype, het logboekniveau, de headers en andere opties kunnen worden geconfigureerd tijdens het maken van een verbinding. Configureer alle vereiste opties door een van de HubConnectionBuilder methoden in te voegen.Build Start de verbinding met 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);                
            }
        }
    }
}

Verbroken verbinding verwerken

Automatisch opnieuw verbinding maken

De HubConnection kan worden geconfigureerd om automatisch opnieuw verbinding te maken met behulp van de WithAutomaticReconnect methode op de HubConnectionBuilder. Standaard wordt er niet automatisch opnieuw verbinding gemaakt.

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

Zonder parameters configureert WithAutomaticReconnect() de client om respectievelijk 0, 2, 10 en 30 seconden te wachten voordat elke poging om opnieuw verbinding te maken, stopt na vier mislukte pogingen.

Voordat u opnieuw verbinding probeert te maken, wijzigt de HubConnection naar de HubConnectionState.Reconnecting-status en wordt de Reconnecting-gebeurtenis geactiveerd. Dit biedt de mogelijkheid om gebruikers te waarschuwen dat de verbinding is verbroken en om UI-elementen uit te schakelen. Niet-interactieve apps kunnen beginnen met het in wachtrij plaatsen of verwijderen van berichten.

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

Als de client opnieuw verbinding maakt binnen de eerste vier pogingen, gaat de HubConnection client terug naar de Connected status en wordt de Reconnected gebeurtenis geactiveerd. Dit biedt de mogelijkheid om gebruikers te informeren dat de verbinding opnieuw tot stand is gebracht en om berichten uit de wachtrij te halen.

Omdat de verbinding er op de server volledig nieuw uitziet, wordt er een nieuwe ConnectionId verstrekt aan de Reconnected gebeurtenis-handlers.

Warning

De Reconnected parameter van de connectionId gebeurtenis-handler is null als de configuratie van de HubConnection is ingesteld om onderhandeling over te slaan.

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() configureert de HubConnection niet om initiële startfouten opnieuw uit te voeren. Startfouten moeten dus handmatig worden afgehandeld:

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

Als de client niet succesvol opnieuw verbinding maakt binnen de eerste vier pogingen, verandert de HubConnection naar de Disconnected-toestand en wordt de Closed gebeurtenis afgevuurd. Dit biedt de mogelijkheid om de verbinding handmatig opnieuw op te starten of gebruikers te informeren dat de verbinding permanent verloren is gegaan.

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

Als u een aangepast aantal nieuwe verbindingspogingen wilt configureren voordat u de tijdsinstellingen voor opnieuw verbinden verbreekt of wijzigt, accepteert WithAutomaticReconnect een matrix met getallen die de vertraging in milliseconden vertegenwoordigen om te wachten voordat elke poging voor opnieuw verbinden wordt gestart.

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.

In het voorgaande voorbeeld wordt de HubConnection geconfigureerd om opnieuw verbinding te maken direct nadat de verbinding is verbroken. Dit geldt ook voor de standaardconfiguratie.

Als de eerste poging om opnieuw verbinding te maken mislukt, wordt de tweede poging om opnieuw verbinding te maken ook onmiddellijk gestart in plaats van 2 seconden te wachten, net zoals in de standaardconfiguratie.

Als de tweede poging om opnieuw verbinding te maken mislukt, wordt de derde poging om opnieuw verbinding te maken binnen 10 seconden gestart, wat weer lijkt op de standaardconfiguratie.

Het aangepaste gedrag wijkt vervolgens opnieuw af van het standaardgedrag door te stoppen na de derde mislukte poging om opnieuw verbinding te maken. In de standaardconfiguratie is er nog een poging om opnieuw verbinding te maken in een andere 30 seconden.

Als u nog meer controle wilt over de timing en het aantal pogingen om automatisch opnieuw verbinding te maken, accepteert WithAutomaticReconnect een object dat de IRetryPolicy-interface implementeert, met één methode met de naam NextRetryDelay.

NextRetryDelay gebruikt één argument met het type RetryContext. De RetryContext heeft drie eigenschappen: PreviousRetryCount, ElapsedTime en RetryReason, die respectievelijk een long, een TimeSpan en een Exception zijn. Voordat de eerste poging wordt ondernomen om opnieuw verbinding te maken, zullen zowel PreviousRetryCount als ElapsedTime nul zijn, en RetryReason zal de uitzondering zijn die ervoor zorgde dat de verbinding verloren is gegaan. Na elke mislukte poging wordt PreviousRetryCount met één verhoogd, ElapsedTime wordt bijgewerkt met de hoeveelheid tijd die tot nu toe aan het opnieuw verbinden is besteed en RetryReason zal de uitzondering zijn die de vorige poging tot opnieuw verbinden heeft doen falen.

NextRetryDelay moet een TimeSpan-object retourneren dat de tijd aangeeft die moet worden gewacht voor de volgende poging om opnieuw verbinding te maken, of null als de HubConnection object moet stoppen met opnieuw proberen verbinding te maken.

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

U kunt ook code schrijven waarmee uw client handmatig opnieuw wordt verbonden, zoals wordt weergegeven in Handmatig opnieuw verbinding maken.

Handmatig opnieuw verbinding maken

Warning

Vóór 3.0 maakt de .NET-client SignalR niet automatisch opnieuw verbinding. U moet code schrijven waarmee uw client handmatig opnieuw wordt verbonden.

Gebruik de Closed gebeurtenis om te reageren op een verbroken verbinding. U kunt bijvoorbeeld opnieuw verbinding maken automatiseren.

Voor de Closed gebeurtenis is een gedelegeerde nodig die een Task retourneert, waarmee asynchrone code kan worden uitgevoerd zonder gebruik te maken van async void. Als u wilt voldoen aan de handtekening van de gemachtigde in een Closed gebeurtenishandler die synchroon wordt uitgevoerd, retourneert u Task.CompletedTask:

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

De belangrijkste reden voor de asynchrone ondersteuning is dat u de verbinding opnieuw kunt starten. Het starten van een verbinding is een asynchrone actie.

In een Closed handler die de verbinding opnieuw start, kunt u overwegen om te wachten op een willekeurige vertraging om te voorkomen dat de server overbelast raakt, zoals wordt weergegeven in het volgende voorbeeld:

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

Hubmethoden aanroepen vanaf de client

InvokeAsync roept methoden aan op de hub. Geef de naam van de hubmethode en eventuele argumenten door die in de hubmethode zijn gedefinieerd.InvokeAsync SignalR is asynchroon, dus gebruik async en await wanneer u de aanroepen doet.

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

De InvokeAsync methode retourneert een Task die wordt voltooid wanneer de servermethode de uitvoering voltooit. De retourwaarde, indien aanwezig, wordt opgegeven als resultaat van de Task. Eventuele uitzonderingen die door de methode op de server worden gegenereerd, produceren een fout Task. Gebruik await de syntaxis om te wachten totdat de servermethode is voltooid en try...catch de syntaxis voor het afhandelen van fouten.

De SendAsync methode retourneert een Task die is voltooid wanneer het bericht naar de server is verzonden. Er wordt geen retourwaarde opgegeven, omdat dit Task niet wacht totdat de servermethode is voltooid. Eventuele uitzonderingen die optreden op de client tijdens het verzenden van het bericht, zorgen voor een fout Task. Gebruik await en try...catch syntaxis voor het afhandelen van verzendfouten.

Note

Hubmethoden aanroepen vanaf een client wordt alleen ondersteund wanneer u de Azure SignalR Service gebruikt in standaardmodus. Zie voor meer informatie Veelgestelde Vragen.

Clientmethoden aanroepen vanuit hub

Definieer methoden die de hub aanroept met behulp van connection.On na het bouwen, maar voordat de verbinding wordt gestart.

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

De voorgaande code in connection.On wordt uitgevoerd wanneer servercode het oproept met de SendAsync methode.

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

Note

Hoewel de hubzijde van de verbinding sterk getypte berichten ondersteunt, moet de client zich registreren met behulp van de algemene methode HubConnection.On met de naam van de methode. Zie Host ASP.NET Core SignalR in achtergrondservices voor een voorbeeld.

Foutafhandeling en logboekregistratie

Omgaan met fouten met een try-catch-instructie. Inspecteer het Exception object om de juiste actie te bepalen die moet worden uitgevoerd nadat er een fout is opgetreden.

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

Aanvullende bronnen