Saltar al contenido

Práctica recomendada para volver a conectar el cliente .NET de SignalR 2.0 al concentrador del servidor

Puede que se de el caso de que encuentres algún fallo con tu código o trabajo, recuerda probar siempre en un ambiente de testing antes añadir el código al trabajo final.

Finalmente me di cuenta de esto. Esto es lo que he aprendido desde que comencé esta pregunta:

Fondo: Estamos creando una aplicación para iOS con Xamarin / Monotouch y el cliente .NET SignalR 2.0.3. Estamos usando los protocolos SignalR predeterminados, y parece estar usando SSE en lugar de sockets web. Todavía no estoy seguro de si es posible usar sockets web con Xamarin / Monotouch. Todo está alojado en sitios web de Azure.

Necesitábamos que la aplicación se reconectara rápidamente a nuestro servidor SignalR, pero seguíamos teniendo problemas en los que la conexión no se reconectaba por sí sola, o la reconexión tardaba exactamente 30 segundos (debido a un tiempo de espera del protocolo subyacente).

Hubo tres escenarios para los que terminamos probando:

Escenario A: conexión la primera vez que se cargó la aplicación. Esto funcionó a la perfección desde el primer día. La conexión se completa en menos de 0,25 segundos incluso a través de conexiones móviles 3G. (asumiendo que la radio ya está encendida)

Escenario B: volver a conectarse al servidor de SignalR después de que la aplicación estuvo inactiva / cerrada durante 30 segundos. En este escenario, el cliente de SignalR eventualmente se volverá a conectar al servidor por sí solo sin ningún trabajo especial, pero parece esperar exactamente 30 segundos antes de intentar volver a conectarse. (demasiado lento para nuestra aplicación)

Durante este período de espera de 30 segundos, intentamos llamar a HubConnection.Start () que no tuvo ningún efecto. Y llamar a HubConnection.Stop () también lleva 30 segundos. Encontré un error relacionado en el sitio de SignalR que parece estar resuelto, pero seguimos teniendo el mismo problema en la v2.0.3.

Escenario C: reconectarse al servidor de SignalR después de que la aplicación estuvo inactiva / cerrada durante 120 segundos o más. En este escenario, el protocolo de transporte de SignalR ya ha agotado el tiempo de espera, por lo que el cliente nunca se vuelve a conectar automáticamente. Esto explica por qué el cliente a veces, pero no siempre, se reconecta por sí solo. La buena noticia es que llamar a HubConnection.Start () funciona casi instantáneamente como el escenario A.

Así que me tomó un tiempo darme cuenta de que las condiciones de reconexión eran diferentes en función de si la aplicación estaba cerrada durante 30 segundos frente a más de 120 segundos. Y aunque los registros de seguimiento de SignalR iluminan lo que sucede con el protocolo subyacente, no creo que haya una manera de manejar los eventos de nivel de transporte en el código. (el evento Cerrado () se activa después de 30 segundos en el escenario B, instantáneamente en el escenario C; la propiedad estatal dice “Conectado” durante estos períodos de espera de reconexión; no hay otros eventos o métodos relevantes)

Solución:
La solucion es obvia. No estamos esperando que SignalR haga su magia de reconexión. En cambio, cuando se activa la aplicación o cuando se restablece la conexión de red del teléfono, simplemente estamos limpiando los eventos y eliminando la referencia a HubConnection (no podemos deshacernos de ella porque demora 30 segundos, con suerte la recolección de basura se encargará de ello ) y creando una nueva instancia. Ahora todo está funcionando muy bien. Por alguna razón, pensé que deberíamos reutilizar una conexión persistente y reconectarnos en lugar de simplemente crear una nueva instancia.

Establecer un temporizador en el evento desconectado para intentar reconectarse automáticamente es el único método que conozco.

En javascript se hace así:

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

Este es el enfoque recomendado en la documentación:

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

Desde el OP pidiendo un Cliente .NET (una implementación winform a continuación),

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;
        
    
    catch (Exception ex)
    
        Console.WriteLine($"Error: ex.Message");
    
    return connected;


private async void Connection_Closed()
   // A global variable being set in "Form_closing" event 
    // of Form, check if form not closed explicitly to prevent a possible deadlock.
    if(!IsFormClosed) 
    
        // 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")
    

Aquí puedes ver las comentarios y valoraciones de los lectores

Agradecemos que desees confirmar nuestra publicación escribiendo un comentario y puntuándolo te estamos agradecidos.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)


Tags :

Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *