Bonjour à tous,
je suis confronté à un problème qui me semble être un "DeadLock".
je suis en train de développer une application dont une des fonctionnalités est d'afficher en temps réelles des données récupérées sur des équipements distants (en Tcp).
Pour ce faire, j'ai deux threads:
- Thread de Dialogue TCP
- Thread Dispatch Données TCP
Thread Dialog TCP
Son rôle est d'aller chercher cycliquement les données des équipements distant via TCP et de les stocker d'une façon structuré dans une mémoire partagée.
Ce Thread ne pose pas de problème (pour le moment)
Thread Dispatch Données TCP
Ce thread récupère les données de la mémoire partagée du thread de dialogue est les envoie aux fiches ayant besoin de celle-ci.
Pour ce faire, je suis parti sur un principe "d'abonnement" aux données.
A l'ouverture d'une fiche de l'application qui consomme ces données, elle s'abonne aux données en appelant la procédure "EventOnDispatchAdd" en lui passant comme paramètre la procédure de la fiche qui doit être appelé pour afficher les données. Le thread Stock la liste des procédures de fiche dans une variable TList servant comme liste de diffusion.
A la fermeture de cette fiche, elle se désabonne en appelant la procédure "EventOnDispatchDel" qui supprime la procédure de la fiche de la liste de diffusion.
C'est dans ce principe que régulièrement, voir assez souvent que mon application se fige.
Pour éviter les accès simultanées à la liste de diffusion du Thread, j'ai encadré l'utilisation de celle-ci par une section critique.
Mon avis sur les sections critiques est qu'elles peuvent être assimilées comme des mutex mais pour un processus. Est-ce bien cela ?
En tous cas, il me semble que mon application se fige bien sur une "DeadLock" du fait de l'utilisation des sections critiques et conjointement de l'instruction Synchronize du Thread.
En espérant avoir été assez claire dans ma description.
Merci d'avance pour votre aide.
----------------------------------------------------------------------------------
Un extrait du code posant problème vaut mieux qu'un long discours.
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
41
42 { Extrait de la définition, constructeur et destructeur du thread Dispatch } type TNotifyOnDispatchTcp = procedure(aPData: PTcpMsgSrvOutData) of object; type PThDispatchTcp = ^TThDispatchTcp; TThDispatchTcp = class(TThread) private fLock : TRTLCriticalSection; fLstOnDispatch : TList<TNotifyOnDispatchTcp>; procedure Cycle; protected procedure Execute; override; public procedure EventOnDispatchAdd(aProc : TNotifyOnDispatchTcp); procedure EventOnDispatchDel(aProc : TNotifyOnDispatchTcp); // ------------------------------ constructor Create; destructor Destroy; override; end; // ------------------------------------------------------ constructor TThDispatchTcp.Create; begin try fLstOnDispatch := TList<TNotifyOnDispatchTcp>.Create; InitializeCriticalSection(fLock); except on E: Exception do LogTrace(SHRMEMDATALOG_LOG_ERROR,E.Message); end; end; // ------------------------------------------------------ destructor TThDispatchTcp.Destroy; begin fLstOnDispatch.Free; DeleteCriticalSection(fLock); inherited; end;
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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72 { Extrait des procédures qui a mon sens pose problème procédure Cycle => Diffusion des données (appel cyclique par API CreateWaitableTimer) procédure EventOnDispatchAdd => Ajout d'un abonnement procédure EventOnDispatchDel => Supprime un abonnement } procedure TThDispatchTcp.Cycle; var I : Integer; begin try // Récupère les données Tcp de la mémoire fTcpMemData.ReadData(@fMsg); // Diffuse les données EnterCriticalSection(fLock); try for I := 0 to fLstOnDispatch.Count - 1 do Synchronize ( Self, procedure begin fLstOnDispatch[I](@fMsg); end ); finally LeaveCriticalSection(fLock); end; except on E : Exception do LogTrace(SHRMEMDATALOG_LOG_ERROR,E.Message); end; end; // ---------------------------------------------- procedure TThDispatchTcp.EventOnDispatchAdd(aProc : TNotifyOnDispatchTcp); begin try EnterCriticalSection(fLock); try if fLstOnRefresh.IndexOf(aProc) = -1 then fLstOnRefresh.Add(aProc); finally LeaveCriticalSection(fLock); end; except on E: Exception do LogTrace(SHRMEMDATALOG_LOG_ERROR,E.Message); end; end; // ---------------------------------------------- procedure TThDispatchTcp.EventOnDispatchDel(aProc : TNotifyOnDispatchTcp); begin try EnterCriticalSection(fLock); try fLstOnDispatch.Remove(aProc); finally LeaveCriticalSection(fLock); end; except on E: Exception do LogTrace(SHRMEMDATALOG_LOG_ERROR,E.Message); end; end;
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5 { Code a l'ouverture d'un fiche par exemple } thDispatchTcp.EventOnDispatchAdd(Self.RefreshValue);
Partager