BESOIN AIDE SUR LES THREAD

Caribensila Messages postés 2527 Date d'inscription jeudi 15 janvier 2004 Statut Membre Dernière intervention 16 octobre 2019 - 9 juin 2012 à 19:23
cs_barbichette Messages postés 220 Date d'inscription lundi 30 octobre 2000 Statut Membre Dernière intervention 15 juillet 2013 - 15 juin 2012 à 19:08
Cette discussion concerne un article du site. Pour la consulter dans son contexte d'origine, cliquez sur le lien ci-dessous.

https://codes-sources.commentcamarche.net/source/54369-besoin-aide-sur-les-thread

cs_barbichette Messages postés 220 Date d'inscription lundi 30 octobre 2000 Statut Membre Dernière intervention 15 juillet 2013
15 juin 2012 à 19:08
j'ai mis en ligne la version qui marche.
En fait, il y avait, il me semble, un problème entre Timage qui est un composant non fenêtre (sans hwnd), son canvas et les threads.

Merci à tous...
cs_barbichette Messages postés 220 Date d'inscription lundi 30 octobre 2000 Statut Membre Dernière intervention 15 juillet 2013
15 juin 2012 à 18:25
Bon, j'ai trouvé une piste :

dans ma fonction de tracé, je laisse tomber les sections critiques, j'encadre les tracés d'un lock/unlock.
Puis, j'envoie un message à la fenêtre pour rafraichir le timage (et le reste).

procedure TFMain.FunctionCall(...
[...]
begin
Env:=TEnvironnement(sender);

image1.Canvas.lock;

case index of
[...]
end;
image1.Canvas.Unlock;
sendmessage(fmain.Handle,WM_PAINT,0,0);
end;

Je teste encore des choses pour voir...
cs_barbichette Messages postés 220 Date d'inscription lundi 30 octobre 2000 Statut Membre Dernière intervention 15 juillet 2013
15 juin 2012 à 18:06
@Manchester : oui, mon canvas existe. j'ai essayé de dessiner directement dans le canvas de l'écran avec getdc(0) et bitblt, idem.

@IA93 : la modif ne marche pas chez moi...
Par contre, avec un sleep(10) au début de ma fonction de dessin, le tracé est long mais ça marche mieux...
Le tracé ne s'effectue pas dans le bitmap de image1, mais il apparait au moins à l'écran...

Je continue de chercher une explication...
cs_ManChesTer Messages postés 374 Date d'inscription vendredi 20 octobre 2000 Statut Modérateur Dernière intervention 15 janvier 2021
15 juin 2012 à 00:26
Barbichette

tu a tester

un if assigned(montruc.canvas) then
faitceci
else
signale_une_grosse_erreur; ?

Bon Coding...

ManChesTer.
IA93 Messages postés 3 Date d'inscription vendredi 17 octobre 2003 Statut Membre Dernière intervention 26 mars 2008
14 juin 2012 à 23:28
Bonsoir,
Lorsque j'ai voulu compiler le source tel qu'il est à l'origine, j'ai eu une suite d'erreurs car je n'ai que Delphi6-Pro.
Le problème venait des appels à TFormatSettings. j'ai donc cherché à recréer un équivalant à partir d'une documentation.
Et j'ai trouvé entre autre la page suivante:
http://docwiki.embarcadero.com/Libraries/en/System.SysUtils.TFormatSettings

Il y est dit que le contexte n'est peut-être pas toujours SAFE-THREAD !

( C'est peut-être une explication car avec les modifications proposées, mon programme fonctionne sans problème...)

Voici donc ma version D6 de UValues.pas, avec ses suppressions, ou la réécriture de GetNumberValue.

unit UValues;

{-----------------------------}
type
TValue=class
//FFormatSettings:TFormatSettings;

{-----------------------------}
constructor TValue.create;
begin
//GetLocaleFormatSettings(0,FFormatSettings);
//FFormatSettings.DecimalSeparator:='.';

{-----------------------------}
function TValue.GetNumberValue:extended;
var
i, p :integer;
LString : string;
begin
LString:=FString;
result:=-1;
for p:=1 to length(LString) do
if LString[p]='.' then LString[p]:=',';
case FTypevalue of
TypeNone:result:=0;
TypeNumber:result:=FNumber;
TypeString:
begin
try
result:=strtoint(LString);
except
try
result:=strtofloat(LString);
except
SendExcep(format('impossible de convertir "%s" en nombre', [FString]));
end;
end;
end;
TypeBoolean:if FBoolean then result:=1 else result:=0;
TypeArray:result:=Fcount;
end;
end;

{-----------------------------}
procedure TValue.SetNumberValue(v:extended);

//TypeNumber:result:=floattostr(FNumber,FFormatSettings);
TypeNumber:result:=floattostr(FNumber);

{-----------------------------}

( J'ai envoyé une autre version modifiée dans un mail à BarbichetteWorld...)

IA93.
cs_barbichette Messages postés 220 Date d'inscription lundi 30 octobre 2000 Statut Membre Dernière intervention 15 juillet 2013
14 juin 2012 à 22:24
Merci pour ces réponses.
Malheureusement, rien n'y fait...
Je n'y comprend plus rien.
Ca a l'air tellement simple et pourtant, ça ne marche pas.
En fait, il me semble que je dessin dans un canvas qui n'existe plus au moment où je l'appel...

@ManChesTer : j'ai regardé justement ta source avec le thread qui dessin en texte (qui, lui, marche bien), mais je ne vois vraiment pas pourquoi mes essais ne marchent jamais...

Sniff....
IA93 Messages postés 3 Date d'inscription vendredi 17 octobre 2003 Statut Membre Dernière intervention 26 mars 2008
14 juin 2012 à 16:36
Je suggère les modifications minimales suivantes:
-Ajouter un destructor au ThReadRun
-Supprimer toutes les instructions de synchronisation/section critiques car il n'y a qu'un seul thread.
-Lancer le thread par Execute, puis le détruire pour terminer

A chaque clic du Bouton1, le thread et l'interpréteur sont créés, puis détruits à la fin de l'appel. Donc l'exécution du mémo est dynamique...(on peut modifier le mémo!)

Voici la liste des modifications proposées:

unit UMain;

// Liste des modif à effectuer sur UMain.pas //

{---------------------------------------}
TThreadRun=class(tthread)
private
// FLock: TCriticalSection;
protected
constructor Create;
destructor Destroy;
procedure Execute; override;
end;

{---------------------------------------}
var // Global
// FSection: TRTLCriticalSection;

{---------------------------------------}
destructor TThreadRun.Destroy;
begin
inherited Destroy;
end;

{---------------------------------------}
procedure TThreadRun.Execute;
begin
try
t.Run(-1);
except
on E: Exception do FMain.ErreurInterpret;
end;
FMain.FinishInterpret;
end;

{---------------------------------------}
procedure TFMain.FunctionCall(...);

// EnterCriticalSection(FSection);

// LeaveCriticalSection(FSection);

{---------------------------------------}
procedure TFMain.FormCreate(Sender: TObject);

//InitializeCriticalSection(FSection);

{---------------------------------------}
procedure TFMain.Button1Click(Sender: TObject)

// th.Resume;
th.Execute;
th.Terminate;
th.destroy;

{---------------------------------------}
cs_ManChesTer Messages postés 374 Date d'inscription vendredi 20 octobre 2000 Statut Modérateur Dernière intervention 15 janvier 2021
13 juin 2012 à 19:57
Salut,

J'utilise le multithread pour certains affichages le bitmap intermédiaire est une bonne solution
Mais personnellement j'utilise le scanline et les apis windows directement et je n'ai jamais rencontré de problèmes.

procedure Mathread.bmptopanel(pan:tpanel;var bmp:tbitmap);
var dc:hdc;
begin
//travail du bmp sur scanline ou api windows...
dc:=getdc(pan.Handle);
bitblt(dc,0,0,pan.width,pan.height,bmp.Canvas.Handle,0,0,srccopy);
releasedc(pan.Handle,dc);
end;

pan et bmp sont dans public de la définition du thread.

Bon Coding,

ManChesTer.
Cirec Messages postés 3833 Date d'inscription vendredi 23 juillet 2004 Statut Modérateur Dernière intervention 18 septembre 2022 50
10 juin 2012 à 00:42
Salut,

Jean_Jean et Caribensila ont raison à eux deux.

en effet, il faut utiliser un BMP intermédiaire (tampon) et utiliser Lock/UnLock ... avec cette méthode on peut se passer de faire appel à Synchronize.
j'ai pas regardé le code (j'ai pas accès à Delphi en ce moment).
cs_Jean_Jean Messages postés 615 Date d'inscription dimanche 13 août 2006 Statut Membre Dernière intervention 13 décembre 2018 3
9 juin 2012 à 23:32
Salut barbichette
et Cari au passage, ça faisait un bail hein?

Peut-être devrait-tu passer par un Bitmap intermédiaire dans lequel tu dessines ou même un TPaintBox. Comme ça, ça sera plus facile à maintenir l'image...L'avantage d'avoir un Bitmap, c'est qu'il sera plus facile de gérer en transparence au code l'artillerie du HDC etc.

Mais bon, c'est une idée! faut tester...

Sinon, j'ai pas encore abordé la question des sections critiques chez les threads... J'en suis encore au début...

Bien à toi
cs_barbichette Messages postés 220 Date d'inscription lundi 30 octobre 2000 Statut Membre Dernière intervention 15 juillet 2013
9 juin 2012 à 20:29
déjà essayé...
C'est la même chose, d'ailleurs, lock/unlock fait simplement intervenir un section critique.

Non, il me semble que le problème vient plutôt de la gestion des canvas, handle, HDC et autres.

Merci
Caribensila Messages postés 2527 Date d'inscription jeudi 15 janvier 2004 Statut Membre Dernière intervention 16 octobre 2019 18
9 juin 2012 à 19:23
Salut Barbichette,

Je n'ai pas encore regardé ton code mais, perso, quand j'utilise TCanvas dans une application multithread, j'utilise souvent les méthodes Lock/UnLock de TCanvas.
Je trouve que c'est moins problématique que les sections critiques.

En espérant que ça t'aidera...
Rejoignez-nous