@ouiouioui: Et si le thread secondaire se termine avant que le thread principal ait exécuté ta procédure. Que vaut "I" ?
@ouiouioui: Et si le thread secondaire se termine avant que le thread principal ait exécuté ta procédure. Que vaut "I" ?
Alors j'ai testé vite fait et ...
en l'état j'ai direct la barre a 100 donc queue passe a i := 100; sans attendre.
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
73
74
75 Unit Unit2; Interface Uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ComCtrls, StdCtrls; Type TThreadtest = Class(TThread) Private i: integer; Procedure test; Protected Procedure Execute; Override; Public Constructor create; Overload; End; TForm2 = Class(TForm) Button1: TButton; ProgressBar1: TProgressBar; Procedure Button1Click(Sender: TObject); Private { Déclarations privées } Public Procedure threadexit(Sender: TObject); { Déclarations publiques } End; Var Form2: TForm2; Implementation {$R *.dfm} Procedure TForm2.Button1Click(Sender: TObject); Begin TThreadtest.create; End; Procedure TForm2.threadexit(Sender: TObject); Begin MessageDlg('thread exit', mtInformation, [mbOK], 0); End; { test } Constructor TThreadtest.create; Begin Inherited create; FreeOnTerminate := true; // OnTerminate := Form2.threadexit; End; Procedure TThreadtest.test; Begin sleep(5000); Form2.ProgressBar1.Position := i; MessageDlg('progressbarupdate', mtInformation, [mbOK], 0); End; Procedure TThreadtest.Execute; Begin i := 5; Queue( Procedure Begin Repeat sleep(100); inc(i); Application.ProcessMessages; Until i > 50; Form2.ProgressBar1.Position := i; End); // Queue(test); i := 100; Synchronize( Procedure Begin MessageDlg('thread continue', mtInformation, [mbOK], 0); End); End; End.
si je commente Synchronize le thread sort sans exécuter la method dans queue
le thread sort avant que queue change la progressbar, pas d'exception.
Mais bon un postmessage pour récupérer des donnée d'un thread avec une section critique échouera pareil si le thread est fini.
Il existe 3 sortes de gens: ceux qui savent compter et ceux qui ne savent pas.
J'ai dit que ça me posait un problème. Je n'ai pas dit que je ne le voyait jamais ...
Malheureusement je bosse sur un projet ou je vois bien pire tous les jours (une bonne partie des soit disant objets métier ne fonctionne que si tu les poses sur un descendant bien particulier de TForm...)
Mais chaque fois que j'en ai la possibilité (c'est à dire très souvent), j'essaie de ne pas faire pareil.
En fait, c'est plus accessible et plus naturel que le RAD.
Le métier n'est que de l'algorithmie.
L'IHM que du bête affichage de données déjà calculées...
Ce qui complexifie les choses, c'est lorsque tu veux à tout prix que tout se fasse dans l'IDE en design en posant des composants tout fait et ne codant que des événements. Le métier disparait, tu dois tout rammener sur des interactions utilisateurs...
Réussir à faire un truc qui marche correctement est beaucoup plus difficile. Surtout si tu veux que l'appli fasse ce que tu veux, et pas ce que les composants visuels ont prévus de faire à ta place !
Ben en fait, ce n'est pas le MVC, donc tu n'as pas besoin de le savoir. C'est seulement un modèle en couches. Et encore, c'est plus un principe fondammental qu'un modèle.
Tu n'utilise jamais de MVC sans un modèle en couche. Mais tu peux avoir un modèle en couches sans MVC (3-tiers, document-vue...).
Le problème c'est que c'est un coup de bol !Envoyé par ouiouioui
Sans le synchronize, le thread sera sans doute détruit avant que Queue ne soit exécuté. Mais lorsque le thread est détruit, il y a très peu de chances que sa mémoire soit rendue a Windows et que l'espace d'adressage correspondant soit invalidé.
Autrement dit, lorsque le thread principal va exécuter le code de Queue, il pourra lire la mémoire qui n'est plus utilisée, et a même de grandes chances de relire la bonne valeur.
Mais si entre la fin du thread et le traitement de queue, le thread prinicpal réalloue un bloc mémoire qui a pour effet de recycler celle de l'ancien thread, I n'aura plus la bonne valeur !
Si tu l'as bien géré, au moment de traiter le message, tu te rendras compte que le thread est fini...Envoyé par ouiouioui
De plus, le problème n'est pas réellement que le thread soit fini, mais de savoir si les données existent toujours.
Je n'utilise jamais FreeOnTerminate. C'est toujours le thread principal (ou en tout cas celui qui a créé le thread secondaire) qui détruit l'instance du thread secondaire.
Personnellement, en pratique, ce cas de figure ne survient jamais. Lorsque le thread secondaire a terminé son traitement, il poste un message au thread principal pour notifier la fin du travail. A ce moment, le thread principal arrête et détruit le thread secondaire qui ne sert plus.
Pour revenir au sujet de base, je tiens à signaler que l'usage de TBitmap dans le cas présent est une mauvaise idée, et ce pour 2 raisons.
D'abord, les TBitmap sont liés à la VCL et au GDI : ils ne sont donc pas thread-safe ! Même des TBitmap en arrière-plan ne sont pas thread-safe.
Ensuite, les TBitmap et leurs canvas ont des performances de m***e. Or, si j'ai bien compris, il s'agit ici de faire du rendu intensif, puisqu'on veut le paralléliser pour gagner en performances.
Je ne peux qu'encourager l'usage de la bibliothèque Graphics32. Celle-ci est thread-safe et a des performances extraordinaires !
sjrd, ancien rédacteur/modérateur Delphi.
Auteur de Scala.js, le compilateur de Scala vers JavaScript, et directeur technique du Scala Center à l'EPFL.
Découvrez Mes tutoriels.
Je dirais que tous les appels ont été mis dans la queue, mais les messages de repeinture n'étant pas prioritaires et cumulatifs, seul I=100 est dessiné.
La queue est vidée à la destruction du thread. Je dirais que c'est la bonne nouvelle et que ça assure déjà une certaine persistence des données. (Franck Soriano va nous confirmer tous ça )
Les seuls choses qui soient valides dans un PosteMessage tout au long du processus sont ses paramètres.
J'ai un peu toujours l'impression qu'on mélange les threads "OS" (CreateThread) et leurs encapsulation TThread
PostMessage à surtout comme intérêt de prévenir qu'une données "globale" est disponible ou qu'un résultat a été atteint. Si la nature du message et ses paramètres suffisent à sa compréhension, le thread peut se terminer automatiquement. Il y a également les cas où aucun résultat n'est attendu (UDP, mailslots,...)
Perso, j'utilise beaucoup FreeOnTerminate.
A noter que GDI, GDI+, OpenGL, etc. sont maintenant dépréciés par Microsoft (Legacy Graphics) qui pronne le tout-Direct2D.
OuiOuiOui,
Queue, voici un truc très intéressant, nettement plus simple que la ThreadList, cela reprend l'idée de la file d'attente de traitement !
C'est intéressant ce que tu dis là, perso, je n'ai jamais utilise ce système de Bitmap doublé\triplé, je n'ai jamais eu ce type de fonctionnel, ce n'est que de la théorie, tu donnes une info importante, comme toujours la pratique et la théorie ...
Lorsque j'avais du dessin à effectuer, c'était un affichage informatif (genre centre d'aiguillage), si un utilisateur intervenait (seulement quelques clics dans une journée), il ne restait soit pas sur les écrans concernés (donc dessin mis en off) soit c'était via un autre poste (client distant), donc le dessin était dans un pauvre Timer qui lisait la table des états des robots
Les Threads ne bossant eux qu'avec la DB et le TCP\IP pour la connexion PC-PC, PC-AS400 ou PC-Robot
Pour Graphics32, cela revient souvent, idem, je n'ai jamais eu besoin d'un tel extrème !
Même le programme que je maintiens en GDI+, je n'ai pas encore compris à quoi servait le GDI+ et quel était son apport réel sur un GDI normal, faudra que je plonge dans cette partie du code !
@AndNotOr \ Franck SORIANO
C'est vrai que le TThread est vicelard, on l'alloue dans le thread principal, tous ses membres sont accessibles depuis ce dernier, seul execute() est dans un autre thread !
FreeOnTerminate est aussi très pratique, parfois un Thread est général, il tourne jusqu'à la fin de l'appli, j'en ai eu bcp comme ça pour le pilotage de robot, mais parfois, on lance juste une tache en parallèle et une notification de fin, si les ressources sont libérées automatique, c'est fort pratique, il suffit d'avoir un autre objet pour les données !
Tant que l'on sait ce que l'on fait et que l'on le documente, faut pas refuser une bonne méthode juste parce qu'on ne l'aime pas !
Le mieux serait d'encaspuler i dans un objet créé par le main passer en paramètre au constructeur du thread, ainsi plus de doute !
Sinon, on a totalement perdu Focus !
Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
Attention Troll Méchant !
"Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
L'ignorance n'excuse pas la médiocrité !
L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
Il faut avoir le courage de se tromper et d'apprendre de ses erreurs
J'aurais dû écrire DirectxD (x = 2 ou 3)
Mais tu avais compris !.. non ?
La gestion du canal alpha, l'antialiasing et la gestion en natif de différents formats d'images (jpg, png, gif, etc.)
Sinon niveau performance, c'est pas parfait (voir moins bon que GDI) puisqu'entièrement soft et c'est certainement pourquoi MS se tourne vers Direct2D et l'accéleration matériel. (Windows 7 et plus)
Vous avez un bloqueur de publicités installé.
Le Club Developpez.com n'affiche que des publicités IT, discrètes et non intrusives.
Afin que nous puissions continuer à vous fournir gratuitement du contenu de qualité, merci de nous soutenir en désactivant votre bloqueur de publicités sur Developpez.com.
Partager