ASP.NET Core SignalR .NET İstemcisi

ASP.NET Core SignalR .NET istemci kitaplığı, .NET uygulamalarından hub'larla SignalR iletişim kurmanızı sağlar.

Örnek kodu görüntüleme veya indirme (indirme)

Bu makaledeki kod örneği, ASP.NET Core SignalR .NET istemcisini kullanan bir WPF uygulamasıdır.

SignalR .NET istemci paketini yükleme

Microsoft.AspNetCore.SignalR. .NET istemcilerinin hub'lara SignalR bağlanması için istemci paketi gereklidir.

İstemci kitaplığını yüklemek için Paket Yöneticisi Konsolu penceresinde aşağıdaki komutu çalıştırın:

Install-Package Microsoft.AspNetCore.SignalR.Client

Hub'a bağlanma

Bağlantı kurmak için bir HubConnectionBuilder oluşturun ve çağrısında bulunur Build. Bağlantı oluşturulurken hub URL'si, protokol, aktarım türü, günlük düzeyi, üst bilgiler ve diğer seçenekler yapılandırılabilir. yöntemlerinden herhangi birini HubConnectionBuilder içine Buildekleyerek gerekli seçenekleri yapılandırın. ile StartAsyncbağlantıyı başlatın.

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

Kayıp bağlantıyı işleme

Otomatik olarak yeniden bağlanma

, HubConnection üzerindeki HubConnectionBuilderyöntemi kullanılarak WithAutomaticReconnect otomatik olarak yeniden bağlanacak şekilde yapılandırılabilir. Varsayılan olarak otomatik olarak yeniden bağlanmaz.

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

Herhangi bir parametre olmadan, WithAutomaticReconnect() istemciyi her yeniden bağlanma girişimini denemeden önce sırasıyla 0, 2, 10 ve 30 saniye bekleyecek şekilde yapılandırarak başarısız olan dört denemeden sonra durdurulmasını sağlar.

Herhangi bir yeniden bağlanma girişimine başlamadan önce, HubConnection duruma geçirilecek HubConnectionState.Reconnecting ve olayı tetikleyecektir Reconnecting . Bu, kullanıcıları bağlantının kaybolduğu konusunda uyarmak ve kullanıcı arabirimi öğelerini devre dışı bırakmak için bir fırsat sağlar. Etkileşimli olmayan uygulamalar iletileri kuyruğa alma veya bırakma işlemini başlatabilir.

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

İstemci ilk dört denemesinde başarıyla yeniden bağlanırsa, HubConnection duruma geri Connected döner ve olayı başlatır Reconnected . Bu, kullanıcılara bağlantının yeniden kuruldığını ve kuyruğa alınan iletilerin sırasının kaldırıldığını bildirme fırsatı sağlar.

Bağlantı sunucuda tamamen yeni göründüğünden, olay işleyicilerine Reconnected yeni ConnectionId bir sağlanacaktır.

Uyarı

Reconnected anlaşması atlanacak şekilde yapılandırıldıysa olay işleyicisinin connectionId HubConnection parametresi null olur.

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() ilk başlatma hatalarını yeniden denemek için öğesini yapılandırmaz HubConnection , bu nedenle başlatma hatalarının el ile işlenmesi gerekir:

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

İstemci ilk dört denemesinde başarıyla yeniden bağlanamazsa, HubConnection duruma geçirilip Disconnected olayı tetikler Closed . Bu, bağlantıyı el ile yeniden başlatmayı deneme veya kullanıcılara bağlantının kalıcı olarak kaybolduğunu bildirme fırsatı sağlar.

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

Bağlantıyı kesmeden veya yeniden bağlanma zamanlamasını değiştirmeden önce özel sayıda yeniden bağlanma girişimi yapılandırmak için, WithAutomaticReconnect her yeniden bağlantı girişimine başlamadan önce beklenmesi gereken gecikmeyi milisaniye cinsinden gösteren bir sayı dizisini kabul eder.

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.

Yukarıdaki örnek, bağlantı kesildikten hemen sonra yeniden bağlanmayı başlatacak şekilde yapılandırılır HubConnection . Bu, varsayılan yapılandırma için de geçerlidir.

İlk yeniden bağlanma girişimi başarısız olursa, ikinci yeniden bağlanma girişimi de varsayılan yapılandırmada olduğu gibi 2 saniye beklemek yerine hemen başlar.

İkinci yeniden bağlanma girişimi başarısız olursa, üçüncü yeniden bağlanma girişimi 10 saniye içinde başlar ve bu yeniden varsayılan yapılandırmaya benzer.

Daha sonra özel davranış, üçüncü yeniden bağlanma girişimi hatasından sonra durarak varsayılan davranıştan yeniden ayrılır. Varsayılan yapılandırmada 30 saniye içinde bir yeniden bağlanma girişimi daha olacaktır.

Otomatik yeniden bağlanma girişimlerinin zamanlaması ve sayısı üzerinde daha fazla denetime sahip olmak istiyorsanız, WithAutomaticReconnect adlı NextRetryDelaytek bir yöntemi olan arabirimi uygulayan IRetryPolicy bir nesneyi kabul eder.

NextRetryDelay türünde RetryContexttek bir bağımsız değişken alır. üç RetryContext özelliğe sahiptir: PreviousRetryCountsırasıyla ElapsedTime RetryReason, longve olan , TimeSpan ve Exception . İlk yeniden bağlanma girişiminden önce hem hem de PreviousRetryCount ElapsedTime sıfır olur ve RetryReason bağlantının kaybolmasına neden olan Özel Durum olur. Başarısız olan her yeniden deneme girişiminden sonra, PreviousRetryCount bir artırılacak, ElapsedTime şimdiye kadar yeniden bağlanmaya harcanan süreyi yansıtacak şekilde güncelleştirilecek ve RetryReason son yeniden bağlanma girişiminin başarısız olmasına neden olan Özel Durum olacaktır.

NextRetryDelay bir sonraki yeniden bağlanma girişiminden null önce beklenmesi gereken süreyi veya yeniden bağlanmayı durdurması HubConnection gerektiğini gösteren bir TimeSpan döndürmelidir.

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

Alternatif olarak, el ile yeniden bağlanma bölümünde gösterildiği gibi istemcinizi el ile yeniden bağlayacak kod yazabilirsiniz.

El ile yeniden bağlanma

Uyarı

3.0'ın öncesinde için SignalR .NET istemcisi otomatik olarak yeniden bağlanmaz. İstemcinizi el ile yeniden bağlayacak kodu yazmanız gerekir.

Closed Kayıp bir bağlantıya yanıt vermek için olayını kullanın. Örneğin, yeniden bağlanmayı otomatikleştirmek isteyebilirsiniz.

OlayClosed, zaman uyumsuz kodun kullanmadan async voidçalışmasına izin veren bir döndüren bir Tasktemsilci gerektirir. Zaman uyumlu olarak çalışan bir Closed olay işleyicisinde temsilci imzasını karşılamak için döndür:Task.CompletedTask

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

Zaman uyumsuz desteğin temel nedeni bağlantıyı yeniden başlatabilmenizdir. Bağlantı başlatmak zaman uyumsuz bir eylemdir.

Bağlantıyı yeniden başlatan bir Closed işleyicide, aşağıdaki örnekte gösterildiği gibi sunucunun aşırı yüklenmesini önlemek için rastgele bir gecikme beklemeyi göz önünde bulundurun:

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

İstemciden çağrı hub'ı yöntemleri

InvokeAsync hub'da yöntemleri çağırır. Hub yöntemi adını ve hub yönteminde tanımlanan tüm bağımsız değişkenleri öğesine InvokeAsyncgeçirin. SignalRzaman uyumsuz olduğundan, çağrıları yaparken ve await kullanınasync.

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

InvokeAsync yöntemi, sunucu yöntemi döndürdüğünde tamamlanan bir Task döndürür. Varsa dönüş değeri, sonucu Taskolarak sağlanır. sunucudaki yöntemi tarafından oluşturulan tüm özel durumlar hatalı Taskbir oluşturur. Sunucu yönteminin tamamlanmasını beklemek için söz dizimini ve try...catch hataları işlemek için söz dizimini kullanınawait.

yöntemi, SendAsync ileti sunucuya gönderildiğinde tamamlanan bir Task döndürür. Sunucu yöntemi tamamlanana kadar beklemediğinden döndürülen değer sağlanmadı Task . İleti gönderilirken istemcide oluşturulan tüm özel durumlar hatalı Taskbir oluşturur. Gönderme hatalarını işlemek için ve try...catch söz dizimlerini kullanınawait.

Not

İstemciden hub yöntemlerini çağırmak yalnızca Azure SignalR Hizmeti Varsayılan modda kullanılırken desteklenir. Daha fazla bilgi için bkz . Sık Sorulan Sorular (azure-signalr GitHub deposu).

Hub'dan istemci yöntemlerini çağırma

Derlemeden sonra ancak bağlantıyı başlatmadan önce hub'ın çağıran connection.On yöntemlerini tanımlayın.

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

içindeki connection.On yukarıdaki kod, sunucu tarafı kodu yöntemini kullanarak SendAsync çağırdığında çalıştırılır.

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

Not

Bağlantının hub tarafı kesin olarak türlenmiş mesajlaşmayı desteklese de istemcinin yöntem adıyla genel yöntemi HubConnection.On kullanarak kaydolması gerekir. Örnek için bkz . Host ASP.NET Core SignalR in background services.

Hata işleme ve günlüğe kaydetme

Try-catch deyimiyle hataları işleme. Exception Bir hata oluştuktan sonra gerçekleştirecek uygun eylemi belirlemek için nesnesini inceleyin.

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

Ek kaynaklar