[c++ builder] mijn repaint houdt er mee op

Pagina: 1
Acties:

  • elgringo
  • Registratie: Januari 2001
  • Laatst online: 01-02 09:13
Ik heb een proces met een tweede thread, deze tweede thread moet informatie uit een shared memory object (die door een dll gemaakt is) uitlezen en weergeven.

Er zit op het hoofd proces een Image1 die als pointer meegegeven wordt aan de thread. Telkens wordt er een bitmap volgetekend en vervolgens wordt deze copieerd naar Image1 en dan volgt een repaint:

C++:
1
2
3
4
5
void __fastcall ViewThread::DisplayIt()
{
Form1->Image1->Canvas->Draw(0,0,pBitmap);
Form1->Image1->Repaint();
}


deze wordt in the execute while loopt telekens aangeroepen:Synchronize(DisplayIt);

Dit werkt prima na een tijdje (10 seconden) repaint hij niets meer. Als de waarden veranderen worden deze niet gerepaint. Hoe kan dit?

Edit: de methode synchronize wordt gewoon aangeroepen alleen het daadwerkelijke repainten gebeurd niet

[ Voor 11% gewijzigd door elgringo op 21-07-2006 12:02 ]

if broken it is, fix it you should


  • elgringo
  • Registratie: Januari 2001
  • Laatst online: 01-02 09:13
iemand?

if broken it is, fix it you should


  • H!GHGuY
  • Registratie: December 2002
  • Niet online

H!GHGuY

Try and take over the world...

tekenen doe je altijd vanuit de GUI thread dacht ik...

ASSUME makes an ASS out of U and ME


  • Depress
  • Registratie: Mei 2005
  • Laatst online: 12-02 13:20
Hoezo dat? Waarom paint hij dan wel de eerste 10 sec?

  • H!GHGuY
  • Registratie: December 2002
  • Niet online

H!GHGuY

Try and take over the world...

hij zal't wel doen, maar het gedrag ervan is afaik undefined.

probeer anders even een windows timer te laten aflopen op je form.

ASSUME makes an ASS out of U and ME


  • BoAC
  • Registratie: Februari 2003
  • Laatst online: 14-02 22:57

BoAC

Memento mori

Of nog beter (maar ik weet niet of dat werkt in C++ Builder): vanuit je thread postmessage naar je gui-thread (main-thread) voor het redrawen.

Is trouwens ook beter omdat je niet wilt dat je thread 'wacht' tot het tekenen gedaan is wanneer je systeem druk is ;)

/edit:
Gebruik geen repaint maar een invalidate ;)

[ Voor 12% gewijzigd door BoAC op 22-07-2006 10:12 ]


  • Creepy
  • Registratie: Juni 2001
  • Laatst online: 21:04

Creepy

Tactical Espionage Splatterer

De VCL is qua tekenen niet threadsave. Je dient er dan ook altijd voor te zorgen dat het tekenen door je main thread gebeurt. met bijv. synchronize() kan je dit voor elkaar krijgen. Je zegt dat dit wel wordt aangeroepen maar dat zien we niet in je code. Kan je aangeven hoe je dit gebruikt?

"I had a problem, I solved it with regular expressions. Now I have two problems". That's shows a lack of appreciation for regular expressions: "I know have _star_ problems" --Kevlin Henney


  • elgringo
  • Registratie: Januari 2001
  • Laatst online: 01-02 09:13
BoAC schreef op zaterdag 22 juli 2006 @ 10:11:
Of nog beter (maar ik weet niet of dat werkt in C++ Builder): vanuit je thread postmessage naar je gui-thread (main-thread) voor het redrawen.

Is trouwens ook beter omdat je niet wilt dat je thread 'wacht' tot het tekenen gedaan is wanneer je systeem druk is ;)

/edit:
Gebruik geen repaint maar een invalidate ;)
Dat doet de functie synchronize: in de help:

Executes a method call within the main VCL thread.
typedef void __fastcall (__closure *TThreadMethod)(void);
void __fastcall Synchronize(TThreadMethod &Method);

Description
Synchronize causes the call specified by Method to be executed using the main VCL thread, thereby avoiding multi-thread conflicts. If you are unsure whether a method call is thread-safe, call it from within the Synchronize method to ensure that it executes in the main VCL thread.
Execution of the thread current is suspended while Method executes in the main VCL thread.
Warning: Do not call Synchronize from within the main VCL thread. Doing so leads to an infinite loop.

Note: You can also protect unsafe methods using critical sections or the multi-read exclusive-write synchronizer.

En hij moet er op wachten, omdat de thread daarvoor gemaakt is.

Waarom moet ik geen repaint gaan gebruiken?
Edit: Invalidate() heeft exact hetzelfde, en houdt er na een tijdje ook mee op
Edit2: helemaal niets heeft ook geen zin, hij wordt wel de eerste 10 seconden getekend, maar daarna houd hij er ook mee op.

[ Voor 13% gewijzigd door elgringo op 24-07-2006 10:41 ]

if broken it is, fix it you should


  • elgringo
  • Registratie: Januari 2001
  • Laatst online: 01-02 09:13
Creepy schreef op zaterdag 22 juli 2006 @ 10:12:
De VCL is qua tekenen niet threadsave. Je dient er dan ook altijd voor te zorgen dat het tekenen door je main thread gebeurt. met bijv. synchronize() kan je dit voor elkaar krijgen. Je zegt dat dit wel wordt aangeroepen maar dat zien we niet in je code. Kan je aangeven hoe je dit gebruikt?
in de execute functie in de while loop wordt telkens dit aangeroepen:

Synchronize(DisplayIt); (en de functie diplayit staat in de TS)

In deze loop wordt een tbitmap vol getekend, deze wordt dan met cnavas->draw() volgetekend (zie functie in ts). Na het tekenen wordt tbitmap met nieuwe waarden (kunnen dezelfde zijn) gevuld en dan wordt ie weer getekend.

[ Voor 19% gewijzigd door elgringo op 24-07-2006 10:43 ]

if broken it is, fix it you should


  • elgringo
  • Registratie: Januari 2001
  • Laatst online: 01-02 09:13
Na wat onderzoek blijkt niet dat het repainten niet meer werkt maar dat er wat anders niet goed gaat. Oftewel pBitmap in de thread wordt niet meer aangepast. Waarom weet ik nog niet.

Edit:
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
TCanvas *pCanvas=pBitmap->Canvas;

// ...

if (bScale){
            pCanvas->Brush->Color = clWhite;
            pCanvas->Pen->Color = clBlack; } else {
                          pCanvas->Brush->Color = clRed;
            pCanvas->Pen->Color = clRed;
                }
            pCanvas->Rectangle(0,0,iWidth,iHeight);
            Synchronize(DisplayIt);
}

bScale is een boolean die vanuit de mainthread gewijzigd kan worden. Dit zit erin om hem te testen. Er moet dus een rood vlak getekend worden als bScale uitstaat en een witte met een zwarte rand als hij aanstaat.

Als hij niet meer werkt is er alleen een wit vlak, net als of de pointer naar pCanvas die van pBitmap komt niet meer goed is oid

Edit2
Als ik de bitmap in de while loop aanmaak en aan het einde verwijder doet ie het wel. Kan het zijn dat dit TBitmap toch iets niet goed doet?

[ Voor 80% gewijzigd door elgringo op 24-07-2006 12:21 ]

if broken it is, fix it you should

Pagina: 1