2017-09-27 20 views
0

J'ai créé une classe qui hérite de la classe Signalr Hub et s'exécute au démarrage. Lorsqu'une connexion est établie, des en-têtes personnalisés sont envoyés par le client que j'utilise pour générer un objet utilisateur. Je veux les stocker en mémoire sur le serveur afin que je puisse récupérer la liste et les afficher dans une interface utilisateur. Quelqu'un peut alors utiliser cette interface utilisateur pour afficher les informations utilisateur et effectuer des interactions avec cette connexion. J'ai installé une classe hub dans un projet ASP MVC et j'utilise une application console pour le client. Je peux me connecter correctement et le serveur peut communiquer à nouveau, mais la propriété que j'utilise dans la classe hub pour garder une trace des utilisateurs connectés est remise à zéro chaque fois qu'une demande est faite à la classe hub.Impossible de suivre les utilisateurs connectés à l'aide de la classe de concentrateur Signalr

public class JobRunHandler : Hub 
{ 
    private List<JobRunClient> RunningJobs { get; set; } 

    public JobRunHandler() 
    { 
     if(this.RunningJobs == null) this.RunningJobs = new List<JobRunClient>(); 
} 

public override Task OnConnected() 
{ 
    JobRunClient runclient = new JobRunClient() 
    { 
     ConnectionID = Context.ConnectionId, 
     Someotherstuff = this.GetHeaderInt(Context.Headers["Someotherstuff"]) 
    }; 

    this.RunningJobs.Add(runclient); 
    return base.OnConnected(); 
} 

public override Task OnReconnected() 
{ 
    var existingClient = this.GetConnectingClient(); 
    if (existingClient == null) 
    { 
     JobRunClient runclient = new JobRunClient() 
     { 
      ConnectionID = Context.ConnectionId, 
      Someotherstuff = this.GetHeaderInt(Context.Headers["Someotherstuff"]) 
     }; 

     this.RunningJobs.Add(runclient); 
    } 
    return base.OnReconnected(); 
} 

public override Task OnDisconnected(bool stopCalled) 
{ 
    this.RemoveClient(Context.ConnectionId); 
    return base.OnDisconnected(stopCalled); 
} 

public void TestMethod() 
{ 
    Clients.All.ping(); 
    var client = this.GetConnectingClient(); 
} 

}

J'ai mis des points de rupture dans chaque méthode donc je sais quand il fonctionne. Le client ne se déconnecte jamais ou ne se déconnecte jamais, il n'y a donc aucun problème avec la connexion en cours. Le client se connecte et les déclencheurs de la méthode OnConnected() et la valeur est ajoutée à this.RunningJobs. Le client appelle alors le TestMethod() qui fonctionne, mais quand je vérifie this.RunningJobs il est vide.

Lorsque Clients.All.ping(); s'exécute, il renvoie un ping vers le client. Donc, la connexion est faite avec succès, le serveur maintient la connexion et je peux envoyer un ping au client quand une méthode séparée est appelée, mais pour une raison quelconque, la propriété est en cours de réinitialisation et je ne sais pas pourquoi. Je peux utiliser Redis pour cela si je le dois, mais j'ai vu d'autres personnes utiliser cette stratégie et cela n'a pas été un problème.

Voici le code client J'ai créé pour tester cette (l'application de la console)

var hubConnection = new HubConnection("http://localhost:2497/"); 
    hubConnection.Credentials = CredentialCache.DefaultNetworkCredentials; 
    IHubProxy myHubProxy = hubConnection.CreateHubProxy("JobRunHandler"); 

    myHubProxy.On("ping",() => Console.Write("Recieved ping \n")); 
    hubConnection.Headers.Add("Someotherstuff", "1"); 
    hubConnection.Start().Wait(); 


    while(true) 
    { 
     myHubProxy.Invoke("BroadcastCompletion").ContinueWith(task => 
     { 
      if (task.IsFaulted) 
      { 
       Console.WriteLine("!!! There was an error opening the connection:{0} \n", task.Exception.GetBaseException()); 
      } 

     }).Wait(); 
     Console.WriteLine("Broadcast sent to the server.\n"); 
     Thread.Sleep(4000); 
    } 

Répondre

1

Le moyeu est transitoire. SignalR crée une instance de concentrateur chaque fois qu'une méthode de concentrateur est appelée, de sorte que vous ne pouvez pas stocker d'état dans une propriété d'instance entre les appels.

0

J'ai changé la propriété utilisée pour cela en un ConcurrentDictionary et cela semble faire l'affaire. Cela me permet de stocker les connexions client dans toutes les connexions. J'ai utilisé le code suivant pour cela.

private static readonly ConcurrentDictionary<string, JobRunClient> RunningJobs = new ConcurrentDictionary<string, JobRunClient>(); 
+0

En fait, c'est le fait que son statique qui a fait la différence ... – thab