Bonjour à tous!
J'ai un souci avec une bibliothèque, le programme plante à chaque fois mais sur une valeur aléatoire.
La raison, c'est que la bibliothèque génère un identifiant à l'instanciation d'un objet de type Variable (un objet de leur cru), mais le génère n'importe comment. J'ai tenté de gérer ça de mon coté mais pour le moment je n'ai trouvé aucune solution.
Mon code, qui plante dans le constructeur de CustomVariable (une classe à moi qui hérite de leur classe Variable):
Le code de la bibliothèque:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12 foreach (CustomVariable v in _variablesDeDepart) { v.getResetEventConnecte().WaitOne(3000); String nomVar = v.Name + "_V" + cvc._Num; ParametresCustomVariable pcv = new ParametresCustomVariable(nomVar, false); lock (_objet) { CustomVariable cv = new CustomVariable(_cpu, pcv); cv.LinkName = v.FullName; cvc.Add(cv); } }
Instanciation:
Appelle le constructeur de la classe mère:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6 public Variable(Cpu cpu, string name) : base(cpu, name) { this.Initialize(cpu, cpu, true, true); this.Init(name); cpu.Variables.Add(this); }
Ce constructeur appelle à la fin AddToCBReceivers:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11 public Base(Base parentObj, string name) { this.Initialize(name, true); this.propParent = parentObj; this.propSNMPParent = null; if (parentObj != null) { this.propService = parentObj.Service; } this.AddToCBReceivers(); }
Qui appelle AddID:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4 internal bool AddToCBReceivers() { return this.Service != null && this.Service.AddID(this, ref this.propInternID); }
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 internal bool AddID(object objTarget, ref uint internID) { if (this.InternIDs == null) { return false; } if (this.ActID == 4294967295u) { uint num = 1u; while (this.InternIDs.ContainsKey(num)) { num += 1u; } internID = num; this.InternIDs.Add(num, objTarget); return true; } internID = (this.ActID += 1u); this.InternIDs.Add(internID, objTarget); return true; }
Qui génère un identifiant pour la nouvelle variable via:
En multi-thread ça plante, donc j'ai mis un lock. Le lock ne change absolument rien. Parce que leur code ne fonctionne même pas en single thread si les appels sont très proches les uns des autres dans le temps.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7 uint num = 1u; while (this.InternIDs.ContainsKey(num)) { num += 1u; } internID = num; this.InternIDs.Add(num, objTarget);
Le stacktrace de l'exception:
L'élément a déjà été ajouté. Clé du dictionnaire : '1491' Clé ajoutée : '1491'
à System.Collections.Hashtable.Insert(Object key, Object nvalue, Boolean add)
à System.Collections.Hashtable.Add(Object key, Object value)
à BR.AN.PviServices.Service.AddID(Object objTarget, UInt32& internID)
à BR.AN.PviServices.Base.AddToCBReceivers()
à BR.AN.PviServices.Base..ctor(Base parentObj, String name)
à BR.AN.PviServices.Variable..ctor(Cpu cpu, String name)
à LibDriverAutomate.Model.CustomVariable..ctor(CustomCpu cpu, ParametresCustomVariable parametres) dans c:\Users\Util\Documents\Visual Studio 2013\Projects\LibDriverAutomate\LibDriverAutomate\Model\CustomVariable.cs:ligne 24
à LibDriverAutomate.Business.FonctionnementVariableCollection.traitement() dans c:\Users\Util\Documents\Visual Studio 2013\Projects\LibDriverAutomate\LibDriverAutomate\Business\FonctionnementVariableCollection.cs:ligne 96
à LibDriverAutomate.Business.FonctionnementVariableCollection.traitementTimer(Object sender, EventArgs ea) dans c:\Users\Util\Documents\Visual Studio 2013\Projects\LibDriverAutomate\LibDriverAutomate\Business\FonctionnementVariableCollection.cs:ligne 179
à System.Timers.Timer.MyTimerCallback(Object state)
Je n'ai accès au code de la bibliothèque que grâce à une décompilation, je ne peux pas y toucher, recompiler me prendrait beaucoup de temps (le code généré par le logiciel n'est pas toujours bon).
L'option de reporter le bug à l'entreprise ayant écrit la bibliothèque pourrait fonctionner, mais les fix sont faits des mois après la demande, via des releases publiques (donc ils attendront une nouvelle release pour publier le correctif, si ils le corrigent).
Bref il faut que je trouve une solution de mon coté, j'ai essayé pas mal de choses mais pour le moment sans succès (sauf un énorme Thread.Sleep dans le lock afin de laisser à la bibliothèque le temps de traiter la demande, mais c'est pas réaliste étant donné que ce thread.Sleep est à multiplier par des dizaines de milliers d'appels).
N'hésitez pas à me poser des questions si je me suis mal exprimé.
Merci à vous.
Partager