Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
A biblioteca de clientes .NET SignalR do ASP.NET Core permite que você se comunique com hubs SignalR de aplicativos .NET.
Exibir ou baixar código de exemplo (como baixar)
O exemplo de código neste artigo é um aplicativo WPF que usa o cliente .NET SignalR do ASP.NET Core.
Instalar o pacote SignalR do cliente .NET
O pacote Microsoft.AspNetCore.SignalR.Client é necessário para que os clientes .NET se conectem aos hubs SignalR.
Para instalar a biblioteca de clientes, execute o seguinte comando na janela Console do gerenciador de pacotes:
Install-Package Microsoft.AspNetCore.SignalR.Client
Conectar-se a um hub
Para estabelecer uma conexão, crie um HubConnectionBuilder e chame Build. A URL do hub, o protocolo, o tipo de transporte, o nível de log, os cabeçalhos e outras opções podem ser configurados durante a criação de uma conexão. Configure as opções necessárias inserindo qualquer um dos métodos HubConnectionBuilder em Build. Inicie a conexão com 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);
}
}
}
}
Manipular conexão perdida
Reconectar automaticamente
O HubConnection pode ser configurado para reconectar automaticamente usando o método WithAutomaticReconnect no HubConnectionBuilder. Ele não se reconectará automaticamente por padrão.
HubConnection connection= new HubConnectionBuilder()
.WithUrl(new Uri("http://127.0.0.1:5000/chathub"))
.WithAutomaticReconnect()
.Build();
Sem parâmetros, WithAutomaticReconnect() configura o cliente para aguardar 0, 2, 10 e 30 segundos, respectivamente, antes de tentar cada tentativa de reconexão, parando após quatro tentativas com falha.
Antes de iniciar qualquer tentativa de reconexão, o HubConnection fará a transição para o estado HubConnectionState.Reconnecting e disparará o evento Reconnecting. Isso oferece uma oportunidade de avisar os usuários de que a conexão foi perdida e desabilitar elementos da interface do usuário. Aplicativos não interativos podem começar a enfileirar ou soltar mensagens.
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;
};
Se o cliente se reconectar com êxito em suas quatro primeiras tentativas, o HubConnection fará a transição de volta para o estado Connected e disparará o evento Reconnected. Isso oferece uma oportunidade de informar aos usuários que a conexão foi restabelecida e desativar qualquer mensagem na fila.
Como a conexão parece totalmente nova para o servidor, um novo ConnectionId será fornecido aos manipuladores de eventos Reconnected.
Warning
O parâmetro Reconnected do manipulador de eventos connectionId será nulo se o HubConnection tiver sido configurado para ignorar a negociação.
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() não configurará o HubConnection para repetir falhas iniciais de início, portanto, as falhas de inicialização precisam ser tratadas manualmente:
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);
}
}
}
Se o cliente não se reconectar com êxito em suas quatro primeiras tentativas, o HubConnection fará a transição para o estado Disconnected e disparará o evento Closed. Isso oferece uma oportunidade de tentar reiniciar a conexão manualmente ou informar aos usuários que a conexão foi perdida permanentemente.
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;
};
Para configurar um número personalizado de tentativas de reconexão antes de desconectar ou alterar o tempo de reconexão, WithAutomaticReconnect aceita uma matriz de números que representam o atraso em milissegundos para aguardar antes de iniciar cada tentativa de reconexão.
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.
O exemplo anterior configura o HubConnection para começar a tentar se conectar novamente imediatamente após a conexão ser perdida. Isso também é verdadeiro para a configuração padrão.
Se a primeira tentativa de reconexão falhar, a segunda tentativa de reconexão também será iniciada imediatamente em vez de aguardar 2 segundos como ocorreria na configuração padrão.
Se a segunda tentativa de reconexão falhar, a terceira tentativa de reconexão será iniciada em 10 segundos, o que é, novamente, como a configuração padrão.
Em seguida, o comportamento personalizado diverge novamente do comportamento padrão, parando após a terceira falha de tentativa de reconexão. Na configuração padrão, haveria mais uma tentativa de reconexão em mais 30 segundos.
Se você quiser ter ainda mais controle sobre o tempo e o número de tentativas de reconexão automática, WithAutomaticReconnect aceitará um objeto que implementa a interface IRetryPolicy, que tem um único método chamado NextRetryDelay.
NextRetryDelay usa um único argumento com o tipo RetryContext. O RetryContext tem três propriedades: PreviousRetryCount, ElapsedTime e RetryReason, que são um long, um TimeSpan e um Exception, respectivamente. Antes da primeira tentativa de reconexão, PreviousRetryCount e ElapsedTime serão zero, e RetryReason será a Exceção que causou a perda da conexão. Após cada tentativa de repetição com falha, PreviousRetryCount será incrementado em um, ElapsedTime será atualizado para refletir o tempo gasto na reconexão até agora e RetryReason será a Exceção que causou a falha da última tentativa de reconexão.
NextRetryDelay deve retornar um TimeSpan que representa o tempo de espera antes da próxima tentativa de reconexão ou null se o HubConnection deve parar de se reconectar.
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();
Como alternativa, você pode escrever código que reconectará o cliente manualmente, conforme demonstrado em Reconectar manualmente.
Reconectar manualmente
Warning
Antes da versão 3.0, o cliente .NET para SignalR não se reconecta automaticamente. Você deve escrever um código que reconecte o cliente manualmente.
Use o evento Closed para responder a uma conexão perdida. Por exemplo, talvez você queira automatizar a reconexão.
O evento Closed requer um delegado que retorna um Task, que permite que o código assíncrono seja executado sem usar async void. Para satisfazer a assinatura de delegado em um manipulador de eventos Closed que é executado de forma síncrona, retorne Task.CompletedTask:
connection.Closed += (error) => {
// Do your close logic.
return Task.CompletedTask;
};
O principal motivo para o suporte assíncrono é para que você possa reiniciar a conexão. Iniciar uma conexão é uma ação assíncrona.
Em um manipulador Closed que reinicia a conexão, considere aguardar algum atraso aleatório para evitar sobrecarregar o servidor, conforme mostrado no exemplo a seguir:
connection.Closed += async (error) =>
{
await Task.Delay(new Random().Next(0,5) * 1000);
await connection.StartAsync();
};
Chamar métodos de hub do cliente
InvokeAsync chama métodos no hub. Passe o nome do método do hub e todos os argumentos definidos no método de hub para InvokeAsync.
SignalR é assíncrono, portanto, use async e await ao fazer as chamadas.
await connection.InvokeAsync("SendMessage",
userTextBox.Text, messageTextBox.Text);
O método InvokeAsync retorna um Task que é concluído quando o método de servidor retorna. O valor retornado, se houver, é fornecido como o resultado do Task. Todas as exceções geradas pelo método no servidor produzem um Task com falha. Use a sintaxe await para aguardar a conclusão do método de servidor e a sintaxe try...catch para tratar erros.
O método SendAsync retorna um Task que é concluído quando a mensagem é enviada ao servidor. Nenhum valor retornado é fornecido, pois este Task não aguarda até que o método de servidor seja concluído. Todas as exceções geradas no cliente ao enviar a mensagem produzem um Task com falha. Use a sintaxe await e try...catch para lidar com erros de envio.
Note
Os métodos de hub de chamada de um cliente só têm suporte ao usar o Serviço SignalR do Azure no modo Padrão. Para obter mais informações, consulte Perguntas frequentes.
Chamar métodos de cliente do hub
Defina os métodos que o hub chama usando connection.On após a criação, mas antes de iniciar a conexão.
connection.On<string, string>("ReceiveMessage", (user, message) =>
{
this.Dispatcher.Invoke(() =>
{
var newMessage = $"{user}: {message}";
messagesList.Items.Add(newMessage);
});
});
O código anterior em connection.On é executado quando o código do lado do servidor o chama usando o método SendAsync.
public async Task SendMessage(string user, string message)
{
await Clients.All.SendAsync("ReceiveMessage", user, message);
}
Note
Embora o lado do hub da conexão dê suporte a mensagens fortemente tipadas, o cliente deve se registrar usando o método genérico HubConnection.On com o nome do método. Para obter um exemplo, confira Host ASP.NET Core SignalR em serviços em segundo plano.
Registro em log e tratamento de erros
Tratar erros com uma instrução try-catch. Inspecione o objeto Exception para determinar a ação adequada a ser tomada após a ocorrência de um erro.
try
{
await connection.InvokeAsync("SendMessage",
userTextBox.Text, messageTextBox.Text);
}
catch (Exception ex)
{
messagesList.Items.Add(ex.Message);
}