Bagikan melalui


ASP.NET Core SignalR .NET Client

Pustaka klien ASP.NET Core SignalR .NET memungkinkan Anda berkomunikasi dengan SignalR hub dari aplikasi .NET.

Melihat atau mengunduh kode sampel (cara mengunduh)

Sampel kode dalam artikel ini adalah aplikasi WPF yang menggunakan klien ASP.NET Core SignalR .NET.

SignalR Menginstal paket klien .NET

Microsoft.AspNetCore.SignalR. Paket klien diperlukan agar klien .NET tersambung ke SignalR hub.

Untuk menginstal pustaka klien, jalankan perintah berikut di jendela Konsol Manajer Paket:

Install-Package Microsoft.AspNetCore.SignalR.Client

Menyambungkan ke hub

Untuk membuat koneksi, buat HubConnectionBuilder dan panggil Build. URL hub, protokol, jenis transportasi, tingkat log, header, dan opsi lainnya dapat dikonfigurasi saat membangun koneksi. Konfigurasikan opsi yang diperlukan dengan memasukkan salah satu metode ke HubConnectionBuilder dalam Build. Mulai koneksi dengan 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);                
            }
        }
    }
}

Menangani koneksi yang hilang

Menyambungkan ulang secara otomatis

HubConnection dapat dikonfigurasi untuk terhubung kembali secara otomatis menggunakan WithAutomaticReconnect metode pada HubConnectionBuilder. Ini tidak akan secara otomatis terhubung kembali secara default.

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

Tanpa parameter apa pun, WithAutomaticReconnect() mengonfigurasi klien untuk menunggu masing-masing 0, 2, 10, dan 30 detik sebelum mencoba setiap upaya koneksi ulang, berhenti setelah empat upaya yang gagal.

Sebelum memulai upaya koneksi ulang, HubConnection akan beralih ke HubConnectionState.Reconnecting status dan mengaktifkan Reconnecting peristiwa. Ini memberikan kesempatan untuk memperingatkan pengguna bahwa koneksi telah hilang dan untuk menonaktifkan elemen UI. Aplikasi non-interaktif dapat mulai mengantre atau menghilangkan pesan.

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

Jika klien berhasil terhubung kembali dalam empat upaya pertamanya, HubConnection akan transisi kembali ke Connected status dan menembakkan Reconnected peristiwa. Ini memberikan kesempatan untuk memberi tahu pengguna bahwa koneksi telah dipublikasikan kembali dan menghapus antrean pesan yang diantrekan.

Karena koneksi terlihat sama sekali baru ke server, baru ConnectionId akan disediakan untuk penanganan Reconnected aktivitas.

Peringatan

Parameter Reconnected penanganan connectionId aktivitas akan null jika HubConnection dikonfigurasi untuk melewati negosiasi.

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() tidak akan mengonfigurasi HubConnection untuk mencoba kembali kegagalan awal, jadi kegagalan mulai perlu ditangani secara manual:

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

Jika klien tidak berhasil menyambungkan kembali dalam empat upaya pertamanya, HubConnection akan beralih ke Disconnected status dan mengaktifkan Closed peristiwa. Ini memberikan kesempatan untuk mencoba memulai ulang koneksi secara manual atau memberi tahu pengguna bahwa koneksi telah hilang secara permanen.

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

Untuk mengonfigurasi jumlah kustom upaya koneksi ulang sebelum memutuskan atau mengubah waktu koneksi ulang, WithAutomaticReconnect menerima array angka yang mewakili penundaan dalam milidetik untuk menunggu sebelum memulai setiap upaya koneksi ulang.

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.

Contoh sebelumnya mengonfigurasi HubConnection untuk mulai mencoba menyambungkan kembali segera setelah koneksi hilang. Ini juga berlaku untuk konfigurasi default.

Jika upaya koneksi ulang pertama gagal, upaya koneksi ulang kedua juga akan segera dimulai alih-alih menunggu 2 detik seperti dalam konfigurasi default.

Jika upaya koneksi ulang kedua gagal, upaya koneksi ulang ketiga akan dimulai dalam 10 detik yang lagi seperti konfigurasi default.

Perilaku kustom kemudian beralih lagi dari perilaku default dengan berhenti setelah kegagalan upaya koneksi ulang ketiga. Dalam konfigurasi default akan ada satu lagi upaya sambungkan kembali dalam 30 detik lagi.

Jika Anda ingin kontrol yang lebih besar atas waktu dan jumlah upaya koneksi ulang otomatis, WithAutomaticReconnect menerima objek yang mengimplementasikan IRetryPolicy antarmuka, yang memiliki satu metode bernama NextRetryDelay.

NextRetryDelay mengambil satu argumen dengan jenis RetryContext. memiliki RetryContext tiga properti: PreviousRetryCount, ElapsedTime dan RetryReason, yang masing-masing adalah long, a TimeSpan dan Exception . Sebelum upaya koneksi ulang pertama, dan PreviousRetryCount ElapsedTime akan menjadi nol, dan RetryReason akan menjadi Pengecualian yang menyebabkan koneksi hilang. Setelah setiap upaya coba lagi yang gagal, PreviousRetryCount akan bertambah satu, ElapsedTime akan diperbarui untuk mencerminkan jumlah waktu yang dihabiskan untuk menyambungkan kembali sejauh ini, dan RetryReason akan menjadi Pengecualian yang menyebabkan upaya koneksi ulang terakhir gagal.

NextRetryDelay harus mengembalikan TimeSpan yang mewakili waktu untuk menunggu sebelum upaya koneksi ulang berikutnya atau null jika HubConnection harus berhenti menyambungkan kembali.

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

Atau, Anda dapat menulis kode yang akan menghubungkan kembali klien Anda secara manual seperti yang ditunjukkan dalam Sambungkan kembali secara manual.

Menyambungkan ulang secara manual

Peringatan

Sebelum 3.0, klien .NET untuk SignalR tidak terhubung kembali secara otomatis. Anda harus menulis kode yang akan menghubungkan kembali klien Anda secara manual.

Closed Gunakan peristiwa untuk merespons koneksi yang hilang. Misalnya, Anda mungkin ingin mengotomatiskan koneksi ulang.

Kejadian ini Closed memerlukan delegasi yang mengembalikan Task, yang memungkinkan kode asinkron berjalan tanpa menggunakan async void. Untuk memenuhi tanda tangan delegasi dalam Closed penanganan aktivitas yang berjalan secara sinkron, kembalikan Task.CompletedTask:

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

Alasan utama dukungan asinkron adalah agar Anda dapat memulai ulang koneksi. Memulai koneksi adalah tindakan asinkron.

Closed Dalam handler yang memulai ulang koneksi, pertimbangkan untuk menunggu beberapa penundaan acak untuk mencegah kelebihan beban server, seperti yang ditunjukkan dalam contoh berikut:

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

Metode hub panggilan dari klien

InvokeAsync memanggil metode di hub. Teruskan nama metode hub dan argumen apa pun yang ditentukan dalam metode hub ke InvokeAsync. SignalR asinkron, jadi gunakan async dan await saat melakukan panggilan.

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

Metode InvokeAsync mengembalikan yang Task selesai ketika metode server kembali. Nilai pengembalian, jika ada, disediakan sebagai hasil dari Task. Setiap pengecualian yang dilemparkan oleh metode di server menghasilkan kesalahan Task. Gunakan await sintaks untuk menunggu metode server selesai dan try...catch sintaks untuk menangani kesalahan.

Metode SendAsync mengembalikan yang Task selesai ketika pesan telah dikirim ke server. Tidak ada nilai pengembalian yang disediakan karena ini Task tidak menunggu sampai metode server selesai. Setiap pengecualian yang dilemparkan pada klien saat mengirim pesan menghasilkan kesalahan Task. Gunakan await dan try...catch sintaks untuk menangani kesalahan pengiriman.

Catatan

Metode hub panggilan dari klien hanya didukung saat menggunakan Layanan Azure SignalR dalam mode Default . Untuk informasi selengkapnya, lihat Tanya Jawab Umum (azure-signalr repositori GitHub).

Memanggil metode klien dari hub

Tentukan metode yang digunakan connection.On hub setelah membangun, tetapi sebelum memulai koneksi.

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

Kode sebelumnya dalam connection.On berjalan ketika kode sisi server memanggilnya menggunakan SendAsync metode .

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

Catatan

Meskipun sisi hub koneksi mendukung olahpesan yang ditik dengan kuat, klien harus mendaftar menggunakan metode HubConnection.On generik dengan nama metode . Misalnya, lihat Host ASP.NET Core SignalR di layanan latar belakang.

Penanganan kesalahan dan pengelogan

Menangani kesalahan dengan pernyataan try-catch. Exception Periksa objek untuk menentukan tindakan yang tepat untuk diambil setelah terjadi kesalahan.

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

Sumber Daya Tambahan: