Trop de changements sur un Form = plantage (Borlandc++Builder)

claudiusenshortus Messages postés 4 Date d'inscription dimanche 4 juin 2006 Statut Membre Dernière intervention 15 février 2011 - 9 févr. 2011 à 16:28
cs_rt15 Messages postés 3874 Date d'inscription mardi 8 mars 2005 Statut Modérateur Dernière intervention 7 novembre 2014 - 29 mai 2011 à 16:47
Bonjour,
Je suis de retour sur le forum avec une nouvelle question.

Mon problème:
En c++ avec Borland C++ Builder 6.0, j'utilise des Forms et des threads.
Et j'ai 2 questions (dont 1 pseudo réponse) :

- pourquoi les ShowMessage(); appelés depuis des threads font tout planter ?
J'avais fait une recherche à l'époque, et la solution est de ne pas les utiliser. Barbare, mais efficace.

- pourquoi lorsque l'on fait changer trop de chose sur un Form par des threads, il plante ? Ex : un Shape ou un Label qui va changer très souvent, surtout pour un Shape qui est de grande taille.
Pour le Label, je n'ai plus souvenir de quand date mon dernier problème (on oubli).
Pour le shape, j'ai réduit sa taille au mini, mais le bug n'est pas loin.
Mais aujourd'hui, j'ai le même problème avec un TabSheet.
Dans mon Form, j'ai un "gros" TabSheet (5 onglets, de la taille de la fenêtre, de la taille de l'écran). Si je clic d'onglets à onglets, tout va bien. Mais si ce changement se fait par le programme lui-même, le changement se fait, la fenêtre se fige et aucune exception n'est levée (j'ai des try/catch(Exception &exception)/catch(...) qui enregistrent les erreurs sur fichier).
Voici 2/3 extraits:
le fichier du projet:

 
WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR lpCmdLine, int)
{
try
{
Application->Initialize();
Application->CreateForm(__classid(TForm1), &Form1);
Application->Run();
...


le fichier du Form avec le thread:

 
DWORD WINAPI ThreadOngletsPageControl(LPVOID lpParam)
{
...
case ONGLET_TEMPERATURES:
{	Form1->PageControl1->ActivePage = Form1->TabSheetTemperatures;
...

La fonction qui crée le thread: (désolé, la mise en page a sauté)

 
tempoThreadOngletsPageControl  = 800; //ms
lpThreadAttributes_unit_maison      = NULL;	        //pointer to thread security attributes
dwStackSize_unit_maison             = 0;	          //initial thread stack size, in bytes
lpStartAddress_unit_maison          = &ThreadOngletsPageControl;  //pointer to thread function
lpParameter_unit_maison             = NULL;	        //argument for new thread
dwCreationFlags_unit_maison         = NULL;	        //creation flags(CREATE_SUSPENDED...)
handleThreadOngletsPageControl = CreateThread( lpThreadAttributes_unit_maison,
dwStackSize_unit_maison,
lpStartAddress_unit_maison,
lpParameter_unit_maison,
dwCreationFlags_unit_maison,							lpThreadId_unit_maison);
priorityThreadOngletsPageControl = THREAD_PRIORITY_NORMAL;//2 points below normal priority for the priority class.
if(!SetThreadPriority(handleThreadOngletsPageControl,priorityThreadOngletsPageControl))



Ce sont les lignes
Form1->PageControl1->ActivePage = Form1->TabSheetTemperatures;

qui font planter le programme.

Alors, dans mon désespoir, j'ai essayé de mettre ces changements dans une autre fonction et de faire appel à cette fonction depuis le thread (c'est con, mais on ne sait jamais)--> ça plante toujours.

J'ai ajouté des trucs comme


 
Form1->PageControl1->Update();
Form1->PageControl1->Repaint();
 
Form1->Update();
Form1->Repaint();
...


Mais rien y fait.

Par contre, si je fais ce changement d'onglet depuis un clic sur un bouton (ou autre, mais sans passer par le thread), ça marche.

 
void __fastcall TForm1::Button27Click(TObject *Sender)
{    Form1->PageControl1->ActivePage = Form1->TabSheetTemperatures;
}

Donc le problème vient bien du thread.


J'ai une petite idée, mais mes compétences se limitent ici : ne serait-ce pas un problème de mémoire du thread ?
En tout cas, dans le gestionnaire des tâches de Windows, j'utilise 0% du proc et pas grand chose en mémoire, et rien ne change après plantage.

Voila, à vous et merci.

3 réponses

BruNews Messages postés 21040 Date d'inscription jeudi 23 janvier 2003 Statut Modérateur Dernière intervention 21 août 2019
9 févr. 2011 à 20:54
Tu es certain qu'il n'y a pas de "Borlanderie" pour gérer les threads ???

On fait soit en WinAPI soit autre chose.

ciao...
BruNews, MVP VC++
0
claudiusenshortus Messages postés 4 Date d'inscription dimanche 4 juin 2006 Statut Membre Dernière intervention 15 février 2011
15 févr. 2011 à 07:59
Je ne vois pas de quoi tu parles, je ne connais qu'une seule façon de faire (celle de mon message).
Si tu en sais plus, peux-tu me mettre sur le bon chemin.

De mon coté, je vais voir comment on peut les gérer d'une façon différente.

D'ici là, pour me dépanner, j'ai utilisé un evenement qui arrive souvent afin d'avoir une sorte de "thread" pour les mises à jour de l'affichage. C'est moche, mais ça fonctionne.

void __fastcall TForm1::FormCanResize(TObject *Sender, int &NewWidth,
int &NewHeight, bool &Resize)
{	Form1->mAJOngletPageControl();
//miseAJourAffichage();
}
0
cs_rt15 Messages postés 3874 Date d'inscription mardi 8 mars 2005 Statut Modérateur Dernière intervention 7 novembre 2014 13
29 mai 2011 à 16:47
Bonjour,

Désolé pour la réponse tardive.
Il y a bien une Borlanderie, car la VCL n'est pas thread safe. Il faut donc utiliser Synchronize pour que les threads secondaires demandent au thread principal d'appeler la VCL lui même.

Cherche Synchronize dans l'aide de C++ Builder ou sur le net, ici par exemple.
0
Rejoignez-nous