Bonjour,

J'ai créé un service WCF qui permet de lancer un ensemble de service.

Ce serveur WCF contient plusieurs listes génériques de type List<myObject>, dont une liste qui contient la liste des utilisateurs actuellement connectés.
Le service fait des callback en temps réel à tous mes utilisateurs connectés en fonction des événements qui se produisent sur mon service WCF.

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
 
       /// <summary>
       /// Liste des utilisateur qui se sont authentifiés sur le serveur
       /// </summary>
       private static readonly List<ICallbackScheduler> subscribers = new List<ICallbackScheduler>();
Lorsqu'un utilisateur se connecte ou se déconnecte je mets à jour cette liste en faisant un "Add" ou un "Remove", voir exemple ci-dessous.

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
 
        /// <summary>
        /// Méthode permettant de s'inscrire sur l'ordonnanceur en tant qu'utilisateur
        /// </summary>
        public void suscribeUser(UserAcompt userAcompt)
        {
            try
            {
                if (userAcompt == null)
                    throw new NullReferenceException("Le profil utilisateur ne peut être NULL");
 
                // -- Ajout de l'utilisateur à la liste
                // -- des utilisateurs connectés
                // ------------------------------------
                if (UserAcomptCollection.searchById(this.listUsers, UserAcompt.LIdUser) == null)
                    this.listUsers.Add(UserAcompt);
 
                // -- Création du canal callback permettant de
                // -- s'assurer de la connexion client / scheduler
                // --------------------------------------------
                ICallbackScheduler callbackScheduler = OperationContext.Current.GetCallbackChannel<ICallbackScheduler>();
                ICommunicationObject obj = (ICommunicationObject)callbackScheduler;
                obj.Closed += obj_Closed;
                obj.Faulted += obj_Closed;
 
                if (!subscribers.Contains(callbackScheduler))
                    subscribers.Add(callbackScheduler);
 
                // -- Appel de la méthode callback
                // -- sur les utilisateurs connectés
                // ---------------------------------
                foreach (ICallbackScheduler ic in subscribers.ToList())
                    ic.userConnected(userAcompt);
            }
            catch (NullReferenceException) { }
            catch (Exception ex)
            {
                adviseClientsAboutSchedulerException("Scheduler.suscribeUser : " + ex.Message);
            }
        }
Et parfois j'ai une erreur du type "collection was modified ...".
J'imagine qu'il arrive qu'un utilisateur se connecte ou déconnecte alors que je suis en train de diffuser de l'information à toute ma liste en bouclant sur cette liste.

Comment est ce que je peux sécuriser cela ? Par un lock ?

Mon service est configuré de cette manière

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
 
    /// <summary>
    /// Service proposés au client sur l'ordonnanceur
    /// </summary>
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Reentrant)]
    public class GTMScheduler : IGTMScheduler
J'ai cru comprendre qu'en ConcurrencyMode je pouvais mettre la valeur "Multiple", est ce que ça peut m'aider ?

Merci pour votre aide.