Klient platformy .NET platformy ASP.NET Core SignalR
Biblioteka klienta platformy .NET platformy ASP.NET Core SignalR umożliwia komunikację z koncentratorami SignalR z aplikacji platformy .NET.
Wyświetl lub pobierz przykładowy kod (jak pobrać)
Przykładowy kod w tym artykule to aplikacja WPF korzystająca z klienta platformy .NET platformy .NET platformy ASP.NET Core SignalR .
Instalowanie pakietu klienta platformy SignalR .NET
Microsoft.AspNetCore .SignalR. Pakiet klienta jest wymagany dla klientów platformy .NET w celu nawiązania połączenia z SignalR koncentratorami.
Aby zainstalować bibliotekę klienta, uruchom następujące polecenie w oknie konsoli Menedżer pakietów:
Install-Package Microsoft.AspNetCore.SignalR.Client
Nawiązywanie połączenia z koncentratorem
Aby nawiązać połączenie, utwórz element i wywołaj metodę HubConnectionBuilder
Build
. Adres URL centrum, protokół, typ transportu, poziom dziennika, nagłówki i inne opcje można skonfigurować podczas tworzenia połączenia. Skonfiguruj wszystkie wymagane opcje, wstawiając dowolną metodę HubConnectionBuilder
do Build
metody . Uruchom połączenie za pomocą polecenia 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);
}
}
}
}
Obsługa utraconego połączenia
Automatyczne ponowne nawiązywanie połączenia
Można HubConnection go skonfigurować tak, aby automatycznie ponownie nawiązać połączenie przy użyciu WithAutomaticReconnect
metody w pliku HubConnectionBuilder. Domyślnie nie zostanie automatycznie ponownie nawiązane połączenie.
HubConnection connection= new HubConnectionBuilder()
.WithUrl(new Uri("http://127.0.0.1:5000/chathub"))
.WithAutomaticReconnect()
.Build();
Bez żadnych parametrów WithAutomaticReconnect()
klient konfiguruje odpowiednio odczekanie 0, 2, 10 i 30 sekund przed próbą ponownego nawiązania połączenia, zatrzymanie po czterech nieudanych próbach.
Przed rozpoczęciem wszelkich ponownych HubConnection
prób nawiązania połączenia program przejdzie do HubConnectionState.Reconnecting
stanu i uruchomi Reconnecting
zdarzenie. Zapewnia to możliwość ostrzeżenia użytkowników o utracie połączenia i wyłączeniu elementów interfejsu użytkownika. Aplikacje nieinterakcyjne mogą rozpoczynać kolejkowanie lub upuszczać komunikaty.
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;
};
Jeśli klient pomyślnie połączy się ponownie w ramach pierwszych czterech prób, HubConnection
nastąpi powrót do Connected
stanu i wyzwolenie Reconnected
zdarzenia. Zapewnia to możliwość poinformowania użytkowników o ponownym opublikowaniu połączenia i usunięciu z kolejki wszystkich komunikatów w kolejce.
Ponieważ połączenie wygląda zupełnie nowe na serwerze, ConnectionId
nowe zostaną udostępnione programom obsługi zdarzeń Reconnected
.
Ostrzeżenie
Reconnected
Parametr programu obsługi connectionId
zdarzeń będzie miał wartość null, jeśli HubConnection
parametr został skonfigurowany do pomijania negocjacji.
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()
Program nie skonfiguruje elementu , aby ponowić HubConnection
próbę początkowych niepowodzeń uruchamiania, dlatego błędy uruchamiania muszą być obsługiwane ręcznie:
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);
}
}
}
Jeśli klient nie połączy się ponownie w ramach pierwszych czterech prób, HubConnection
nastąpi przejście do Disconnected
stanu i wyzwolenie Closed zdarzenia. Dzięki temu można spróbować ponownie uruchomić połączenie ręcznie lub poinformować użytkowników, że połączenie zostało trwale utracone.
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;
};
Aby skonfigurować niestandardową liczbę ponownych prób ponownego połączenia przed rozłączeniem lub zmianą czasu ponownego połączenia, WithAutomaticReconnect
akceptuje tablicę liczb reprezentujących opóźnienie w milisekundach oczekiwania przed rozpoczęciem każdej próby ponownego nawiązania połączenia.
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.
W poprzednim przykładzie skonfigurowana jest wartość HubConnection
, aby rozpocząć ponowne nawiązywanie połączeń natychmiast po utracie połączenia. Dotyczy to również konfiguracji domyślnej.
Jeśli pierwsza próba ponownego nawiązania połączenia zakończy się niepowodzeniem, druga próba ponownego połączenia zostanie również uruchomiona natychmiast zamiast czekać 2 sekundy, tak jak w konfiguracji domyślnej.
Jeśli druga próba ponownego nawiązania połączenia zakończy się niepowodzeniem, trzecia próba ponownego nawiązania połączenia rozpocznie się w ciągu 10 sekund, co jest ponownie podobne do konfiguracji domyślnej.
Zachowanie niestandardowe ponownie odbiega od domyślnego zachowania, zatrzymując się po trzecim niepowodzeniu ponownego nawiązania połączenia. W konfiguracji domyślnej będzie jeszcze jedna próba ponownego nawiązania połączenia w ciągu kolejnych 30 sekund.
Jeśli chcesz mieć jeszcze większą kontrolę nad chronometrażem i liczbą automatycznych ponownych prób ponownego łączenia, WithAutomaticReconnect
akceptuje obiekt implementjący IRetryPolicy
interfejs, który ma jedną metodę o nazwie NextRetryDelay
.
NextRetryDelay
przyjmuje jeden argument z typem RetryContext
. Obiekt RetryContext
ma trzy właściwości: PreviousRetryCount
, ElapsedTime
i RetryReason
, które są long
odpowiednio , i TimeSpan
Exception
. Przed pierwszą ponowną próbą nawiązania połączenia zarówno, jak PreviousRetryCount
i ElapsedTime
będzie zero, a RetryReason
element będzie wyjątkiem, który spowodował utratę połączenia. Po każdej nieudanej próbie PreviousRetryCount
ponawiania próby zostanie zwiększona o jeden, zostanie zaktualizowana tak, ElapsedTime
aby odzwierciedlała ilość czasu spędzonego na ponownym połączeniu do tej pory i RetryReason
będzie to wyjątek, który spowodował ostatnią ponowną próbę nawiązania połączenia.
NextRetryDelay
Musi zwrócić przedział czasu reprezentujący czas oczekiwania przed kolejną ponowną próbą nawiązania połączenia lub null
jeśli HubConnection
element powinien przestać ponownie łączyć się.
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();
Alternatywnie możesz napisać kod, który ponownie połączy klienta ręcznie, jak pokazano w temacie Ręczne ponowne nawiązywanie połączenia.
Ręczne ponowne nawiązywanie połączenia
Ostrzeżenie
Przed wersją 3.0 klient SignalR platformy .NET nie łączy się automatycznie ponownie. Musisz napisać kod, który będzie ponownie łączyć klienta ręcznie.
Closed Użyj zdarzenia, aby odpowiedzieć na utracone połączenie. Na przykład możesz zautomatyzować ponowne nawiązywanie połączenia.
Zdarzenie Closed
wymaga delegata zwracającego Task
element , który umożliwia uruchamianie kodu asynchronicznego bez użycia polecenia async void
. Aby spełnić wymagania podpisu delegata w procedurze Closed
obsługi zdarzeń, która jest uruchamiana synchronicznie, zwróć polecenie Task.CompletedTask
:
connection.Closed += (error) => {
// Do your close logic.
return Task.CompletedTask;
};
Główną przyczyną obsługi asynchronicznego jest możliwość ponownego uruchomienia połączenia. Uruchamianie połączenia jest akcją asynchroniczną.
Closed
W programie obsługi, która uruchamia ponownie połączenie, rozważ oczekiwanie na pewne losowe opóźnienie, aby zapobiec przeciążeniu serwera, jak pokazano w poniższym przykładzie:
connection.Closed += async (error) =>
{
await Task.Delay(new Random().Next(0,5) * 1000);
await connection.StartAsync();
};
Metody centrum wywołań od klienta
InvokeAsync
wywołuje metody w centrum. Przekaż nazwę metody centrum i wszystkie argumenty zdefiniowane w metodzie hub na InvokeAsync
. SignalR jest asynchroniczna, więc użyj polecenia async
i await
podczas wykonywania wywołań.
await connection.InvokeAsync("SendMessage",
userTextBox.Text, messageTextBox.Text);
Metoda InvokeAsync
zwraca wartość Task
, która kończy się po powrocie metody serwera. Wartość zwracana, jeśli istnieje, jest podana jako wynik .Task
Wszelkie wyjątki zgłaszane przez metodę na serwerze generują błąd Task
. Użyj await
składni, aby poczekać na ukończenie metody serwera i try...catch
składnię do obsługi błędów.
Metoda SendAsync
zwraca element Task
, który kończy się po wysłaniu komunikatu do serwera. Nie podano wartości zwracanej, ponieważ nie oczekuje ona Task
na ukończenie metody serwera. Wszelkie wyjątki zgłaszane na kliencie podczas wysyłania komunikatu generują błąd Task
. Używanie składni await
i try...catch
do obsługi błędów wysyłania.
Uwaga
Wywoływanie metod centrum od klienta jest obsługiwane tylko w przypadku korzystania z usługi platformy Azure SignalR w trybie domyślnym . Aby uzyskać więcej informacji, zobacz Często zadawane pytania (azure —signalr repozytorium GitHub).
Wywoływanie metod klienta z centrum
Zdefiniuj metody wywołania koncentratora przy użyciu polecenia connection.On
po utworzeniu, ale przed rozpoczęciem połączenia.
connection.On<string, string>("ReceiveMessage", (user, message) =>
{
this.Dispatcher.Invoke(() =>
{
var newMessage = $"{user}: {message}";
messagesList.Items.Add(newMessage);
});
});
Powyższy kod w programie connection.On
jest uruchamiany, gdy kod po stronie serwera wywołuje go przy użyciu SendAsync
metody .
public async Task SendMessage(string user, string message)
{
await Clients.All.SendAsync("ReceiveMessage", user,message);
}
Uwaga
Chociaż strona piasty połączenia obsługuje silnie typizowane komunikaty, klient musi zarejestrować się przy użyciu metody ogólnej z nazwą metody HubConnection.On . Aby zapoznać się z przykładem, zobacz Host ASP.NET Core SignalR w usługach w tle.
Obsługa błędów i rejestrowanie
Obsługa błędów za pomocą instrukcji try-catch. Sprawdź obiekt, Exception
aby określić właściwą akcję do wykonania po wystąpieniu błędu.
try
{
await connection.InvokeAsync("SendMessage",
userTextBox.Text, messageTextBox.Text);
}
catch (Exception ex)
{
messagesList.Items.Add(ex.Message);
}