Méthode recommandée pour reconnecter le client SignalR 2.0 .NET au concentrateur de serveur

J’utilise SignalR 2.0 avec le client .NET dans une application mobile et je dois donc gérer différents types de déconnexions. Parfois, le client SignalR se reconnecte sans mon aide – et je dois parfois me reconnecter en appelant à nouveau HubConnection.Start (). (puisque SignalR se reconnecte automatiquement comme une partie du temps, je me demande s’il me manque une fonctionnalité ou un paramètre de configuration)

Quelle est la meilleure façon de configurer un client qui se reconnecte automatiquement? J’ai vu des exemples javascript qui gèrent l’événement Closed (), puis se connectent après une n-secondes. Y a-t-il une approche recommandée?

J’ai lu la documentation et plusieurs articles sur la durée de vie des connexions SignalR, mais je ne sais toujours pas comment gérer la reconnexion du client.

Je vous remercie!

    J’ai finalement compris ça. Voici ce que j’ai appris depuis le début de cette question:

    Contexte: Nous construisons une application iOS à l’aide de Xamarin / Monotouch et du client .NET SignalR 2.0.3. Nous utilisons les protocoles SignalR par défaut – et il semble utiliser SSE au lieu de sockets Web. Je ne sais pas encore s’il est possible d’utiliser des sockets Web avec Xamarin / Monotouch. Tout est hébergé via les sites Web Azure.

    Nous avions besoin que l’application se reconnecte rapidement à notre serveur SignalR, mais nous avions toujours des problèmes de connexion qui ne se reconnectaient pas – ou la reconnexion prenait exactement 30 secondes (en raison d’un délai d’expiration du protocole sous-jacent).

    Nous avons testé trois scénarios pour:

    Scénario A – connexion la première fois que l’application a été chargée. Cela a parfaitement fonctionné dès le premier jour. La connexion se termine en moins de 0,25 seconde, même sur les connexions mobiles 3G. (en supposant que la radio est déjà allumée)

    Scénario B – Reconnexion au serveur SignalR après que l’application ait été inactive / fermée pendant 30 secondes. Dans ce scénario, le client SignalR finira par se reconnecter au serveur sans travail particulier – mais il semble attendre exactement 30 secondes avant de tenter de se reconnecter. (beaucoup trop lent pour notre application)

    Pendant cette période d’attente de 30 secondes, nous avons essayé d’appeler HubConnection.Start () qui n’avait aucun effet. Et appeler HubConnection.Stop () prend également 30 secondes. J’ai trouvé un bug apparenté sur le site SignalR qui semble être résolu , mais nous avons toujours le même problème dans la v2.0.3.

    Scénario C – Reconnexion au serveur SignalR après que l’application ait été inactive / fermée pendant 120 secondes ou plus. Dans ce scénario, le protocole de transport SignalR a déjà expiré afin que le client ne se reconnecte jamais automatiquement. Cela explique pourquoi le client se reconnectait parfois, mais pas toujours. La bonne nouvelle est que l’appel de HubConnection.Start () fonctionne presque instantanément comme le scénario A.

    Il m’a donc fallu un moment pour comprendre que les conditions de reconnexion étaient différentes selon que l’application était fermée pendant 30 secondes contre 120 + secondes. Et bien que les journaux de suivi de SignalR éclairent ce qui se passe avec le protocole sous-jacent, je ne pense pas qu’il existe un moyen de gérer les événements de niveau de transport dans le code. (l’événement Closed () se déclenche après 30 secondes dans le scénario B, instantanément dans le scénario C; la propriété State indique “Connecté” pendant ces périodes d’attente de reconnexion, aucun autre événement ou méthode pertinent)

    Solution: La solution est évidente. Nous n’attendons pas que SignalR fasse sa reconnexion magique. Au lieu de cela, lorsque l’application est activée ou lorsque la connexion réseau du téléphone est restaurée, nous nettoyons simplement les événements et dé-référençons la HubConnection (ne peut pas en disposer car cela prend 30 secondes, si tout se passe bien) ) et créer une nouvelle instance. Maintenant, tout fonctionne très bien. Pour une raison quelconque, je pensais que nous devrions réutiliser une connexion persistante et nous reconnecter au lieu de simplement créer une nouvelle instance.

    La seule méthode que je connaisse est la définition d’un minuteur sur l’événement déconnecté pour tenter automatiquement de se reconnecter.

    En javascript c’est comme ça:

    $.connection.hub.disconnected(function() { setTimeout(function() { $.connection.hub.start(); }, 5000); // Restart connection after 5 seconds. }); 

    C’est l’approche recommandée dans la documentation:

    http://www.asp.net/signalr/overview/signalr-20/hubs-api/handling-connection-lifetime-events#clientdisconnect

    Depuis l’OP demandant un client .NET (une implémentation winform ci-dessous),

     private async Task ConnectToSignalRServer() { bool connected = false; try { Connection = new HubConnection("server url"); Hub = Connection.CreateHubProxy("MyHub"); await Connection.Start(); //See @Oran Dennison's comment on @KingOfHypocrites's answer if (Connection.State == ConnectionState.Connected) { connected = true; Connection.Closed += Connection_Closed; } return connected; } catch (Exception ex) { Console.WriteLine("Error"); return false; } } private async void Connection_Closed() { if(!IsFormClosed) // A global variable being set in "Form_closing" event of Form, check if form not closed explicitly to prevent a possible deadlock. { // specify a retry duration TimeSpan retryDuration = TimeSpan.FromSeconds(30); DateTime retryTill = DateTime.UtcNow.Add(retryDuration); while (DateTime.UtcNow < retryTill) { bool connected = await ConnectToSignalRServer(); if (connected) return; } Console.WriteLine("Connection closed") } } 

    Vous pouvez essayer d’invoquer la méthode du serveur à partir de votre Android avant que l’état de reconnexion ne commence à empêcher le problème de reconnexion magique.

    SignalR Hub C #

      public class MyHub : Hub { public void Ping() { //ping for android long polling } } 

    Dans Android

     private final int PING_INTERVAL = 10 * 1000; private boolean isConnected = false; private HubConnection connection; private ClientTransport transport; private HubProxy hubProxy; private Handler handler = new Handler(); private Runnable ping = new Runnable() { @Override public void run() { if (isConnected) { hubProxy.invoke("ping"); handler.postDelayed(ping, PING_INTERVAL); } } }; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); System.setProperty("http.keepAlive", "false"); ..... ..... connection.connected(new Runnable() { @Override public void run() { System.out.println("Connected"); handler.postDelayed(ping, PING_INTERVAL); }); }