Wątki - problem z klasą nie będącą formą

dział ogólny

Wątki - problem z klasą nie będącą formą

Nowy postprzez Corvis » czwartek, 18 marca 2010, 12:45

Witam,

Napisałem sobie następującą klasę:

Kod: Zaznacz cały
TMojaKlasa : public TPaintBox {
  void Maluj();
};


Chciałbym, żeby malowanie odbywało się w oddzielnym wątku. Na stronie cyfrowegobarona http://cyfbar.republika.pl/api2.html#api14 jest sposób jak włączyć wątki dla formatki.

Zrobiłem więć tak ( plik *.h) : ( KSEUDO KOD )

Kod: Zaznacz cały
TMojaKlasa : public TPaintBox {
  private:
    int W_ID;
    unsigned int W_PD;
  public:
    void Maluj();
};


No i plik *.cpp ( KSEUDO KOD )

Tworzę funkcje Wyliczenia1 oraz w Konstruktorze chce uruchomić wątek.

Kod: Zaznacz cały
//------------------------------------------------------------------------
int __fastcall Wyliczenia1(Pointer Parameter) {
// Jak mam się tutaj odwołać do funkcji TMojaKlasa->Maluj();
}
//------------------------------------------------------------------------
TMojaKlasa::TMojaKlasa() {
   W_ID = BeginThread(NULL, 0, Wyliczenia1, this, 0, W_PD);
}
//------------------------------------------------------------------------


No i tutaj mam pytanie jak się odwołać mam do mojej metody Maluj() ??
W Przypadku Formatek jest to proste bo udostępniają instancje obiektu poprzez :

Kod: Zaznacz cały
extern PACKAGE TForm *Form1;


Jak robie coś takiego samego z moją klasą to liner mi krzyczy przy używaniu funkcji Maluj w wątku.
Wiem, że to pytanie bardziej z teori C++ ale będe wdzięczny z pomoc :)

pozdrawiam
"Sukcesy trwają, dopóki ich ktoś nie spieprzy. Porażki są wieczne"

Dr Gregory House
Avatar użytkownika
Corvis
Programista I
Programista I
 
Posty: 880
Dołączył(a): sobota, 26 lipca 2008, 00:31
Podziękował : 80
Otrzymał podziękowań: 30
System operacyjny: WINDOWS 7 64-bity
Kompilator: Praca - C++ Builder XE2 ENTERPRISE - Update 4, Dom - C++ Builder XE4 - Uddate 1
Gadu Gadu: 0
    Windows VistaSafari

Re: Wątki - problem z klasą nie będącą formą

Nowy postprzez polymorphism » czwartek, 18 marca 2010, 17:08

Kod: Zaznacz cały
int __fastcall Wyliczenia1(Pointer Parameter)
{
    ((TMojaKlasa*)Parameter)->Maluj(); //<--- patrz 4 parametr BeginThread
}

W sumie Wyliczenia1 mogłaby być prywatną metodą statyczną klasy TMojaKlasa, wtedy wszystko trzymałoby się kupy.
C++ Reference - opis wszystkich klas STL-a i funkcji C.

Za ten post autor polymorphism otrzymał podziękowanie od:
Corvis
Avatar użytkownika
polymorphism
Doświadczony Programista ● Moderator
Doświadczony Programista ● Moderator
 
Posty: 2156
Dołączył(a): piątek, 19 grudnia 2008, 13:04
Podziękował : 0
Otrzymał podziękowań: 200
System operacyjny: Windows 8.1
Windows 10
Linux Mint 21.1
Kompilator: Visual Studio
Visual Studio Code
MSYS2 (MinGW, clang)
g++
clang
Gadu Gadu: 0
    Windows XPFirefox

Re: Wątki - problem z klasą nie będącą formą

Nowy postprzez Corvis » piątek, 19 marca 2010, 09:20

Dzięki :)

Mam jeszcze pytanko:

Mam własną klasę która dziedziczny po TPaintBox, ma ona metodę
Kod: Zaznacz cały
Malowanie()
która maluje na TBItmap różne rzeczy, następnie bitmapa jest kopiowana na PaintBoxa ( tego z mojej klasy )
Kod: Zaznacz cały
this->Canvas->Draw(0, 0, bitmapa);


No i cały szkopół polega na tym, że funkcja Malowanie() wykonuje miliony obliczeń <- dlatego chce ją wsadzić w inny wątek i po skończeniu obliczeń przekopiować bitmape na PaitBoxa.

Tylko, że cały czas mi się to wywala - rzuca błędami typu. Out of Resources, nieprawidłowe dojście itp. Wiem, że w wątkach nie można odwoływać się do komponentów VCL. Jednak moja metoda Malowanie posiada np:

Kod: Zaznacz cały
// rozmiar bitmapy
   int dlugosc = this->Width - LMargin - RMargin;
   bitmapa->Width =  this->Width;
   bitmapa->Height = this->Height;


Gdzie this->Width to pobranie z mojej klasy aktualnych rozmiarów PaintBoxa. Czy takie coś może być w wątkach ???? Coś mi się chyba wydaję, że nie.

Pozdrawiam
"Sukcesy trwają, dopóki ich ktoś nie spieprzy. Porażki są wieczne"

Dr Gregory House
Avatar użytkownika
Corvis
Programista I
Programista I
 
Posty: 880
Dołączył(a): sobota, 26 lipca 2008, 00:31
Podziękował : 80
Otrzymał podziękowań: 30
System operacyjny: WINDOWS 7 64-bity
Kompilator: Praca - C++ Builder XE2 ENTERPRISE - Update 4, Dom - C++ Builder XE4 - Uddate 1
Gadu Gadu: 0
    Windows VistaSafari

Re: Wątki - problem z klasą nie będącą formą

Nowy postprzez Cyfrowy Baron » piątek, 19 marca 2010, 09:59

Tylko, że cały czas mi się to wywala - rzuca błędami typu. Out of Resources, nieprawidłowe dojście itp.


Dzieje się prawdopodobnie tak dlatego, że Bitmapa lub TPainBox maja za duży rozmiar o czym niewątpliwie świadczy komunikat Out of resources.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: Wątki - problem z klasą nie będącą formą

Nowy postprzez Cyfrowy Baron » piątek, 19 marca 2010, 10:03

Jeżeli chcesz wydajnie i szybko wykonywać operacje graficzne to powinieneś porzucić klasę TCanvas i pomyśleć o GDI+.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: Wątki - problem z klasą nie będącą formą

Nowy postprzez polymorphism » piątek, 19 marca 2010, 10:09

(...) rzuca błędami typu. Out of Resources

Tu albo nie usuwasz bitmap (przy założeniu, że tworzysz je cyklicznie), albo ustawiasz ich rozmiar tak duży, że system nie jest w stanie ich utworzyć.

Czy takie coś może być w wątkach ????

Może, ale powinno być zsynchronizowane. No i tu jest problem. Bo jak zsynchronizować dostęp do właściwości/metod paintbox'a? Zresztą zastanów się, czy wątek koniecznie musi mieć dostęp do paintbox'a, może wystarczy po prostu przekazać mu niezbędne informacje lokalnie.
C++ Reference - opis wszystkich klas STL-a i funkcji C.
Avatar użytkownika
polymorphism
Doświadczony Programista ● Moderator
Doświadczony Programista ● Moderator
 
Posty: 2156
Dołączył(a): piątek, 19 grudnia 2008, 13:04
Podziękował : 0
Otrzymał podziękowań: 200
System operacyjny: Windows 8.1
Windows 10
Linux Mint 21.1
Kompilator: Visual Studio
Visual Studio Code
MSYS2 (MinGW, clang)
g++
clang
Gadu Gadu: 0
    Windows XPFirefox

Re: Wątki - problem z klasą nie będącą formą

Nowy postprzez Corvis » piątek, 19 marca 2010, 11:10

Załączam przykładowy projekt który wylatuje w powietrze. Pisałem to na mega szybko więc wybaczcie za jakość he he he. Poruszajcie np oknem w trakcie działania programu. Wszystko sie posypie. Bitmape - tworzę i usuwam raz.

Pozdrawiam
Nie masz wystarczających uprawnień, aby zobaczyć pliki załączone do tego postu.
"Sukcesy trwają, dopóki ich ktoś nie spieprzy. Porażki są wieczne"

Dr Gregory House
Avatar użytkownika
Corvis
Programista I
Programista I
 
Posty: 880
Dołączył(a): sobota, 26 lipca 2008, 00:31
Podziękował : 80
Otrzymał podziękowań: 30
System operacyjny: WINDOWS 7 64-bity
Kompilator: Praca - C++ Builder XE2 ENTERPRISE - Update 4, Dom - C++ Builder XE4 - Uddate 1
Gadu Gadu: 0
    Windows VistaSafari

Re: Wątki - problem z klasą nie będącą formą

Nowy postprzez polymorphism » piątek, 19 marca 2010, 11:29

Zupełny brak synchronizacji, to jest powód błędów.

Kod: Zaznacz cały
int __fastcall test::Obliczenia(Pointer Parameter) 
{
   (...)

   ExitThread(GetExitCodeThread(Obliczenia,0));//<--- to jest zupełnie bez sensu. Zajrzyj do dokumentacji!
} 


Kod: Zaznacz cały
__fastcall test::~test() 
{
    koniecAplikacji = true; 
    delete bitmapa
; //<--- jaką masz pewność, że wątek wyszedł z Maluj???
} 

Hint: WaitForSingleObject.

Kod: Zaznacz cały
void test::Kopiuj() 
{
    this->Canvas->Draw(0,0,bitmapa); //<--- jaką masz pewność, że wątek wyszedł z Maluj???
    MoznaKopiowac = false; 
} 


Poczytaj sobie o synchronizacji, bo rzadko zdarzają się sytuacje, że nie trzeba synchronizować dostępu do zasobów w aplikacji wielowątkowej.




Kod: Zaznacz cały
class test : public TPaintBox {
    public:             
        bool MoznaKopiowac
;
        bool Namaluj;
        bool koniecAplikacji;
        int flgMalowanie;
        Graphics::TBitmap* bitmapa;
        void __fastcall MyOnPaint(TObject* Sender);
        void Maluj(); 
        void Kopiuj
(); 
        int W_ID
;
        
unsigned int W_PD;
        
static int __fastcall Obliczenia(Pointer Parameter);
};
 

Czy te wszystkie zmienne i metody muszą być publiczne?
C++ Reference - opis wszystkich klas STL-a i funkcji C.
Avatar użytkownika
polymorphism
Doświadczony Programista ● Moderator
Doświadczony Programista ● Moderator
 
Posty: 2156
Dołączył(a): piątek, 19 grudnia 2008, 13:04
Podziękował : 0
Otrzymał podziękowań: 200
System operacyjny: Windows 8.1
Windows 10
Linux Mint 21.1
Kompilator: Visual Studio
Visual Studio Code
MSYS2 (MinGW, clang)
g++
clang
Gadu Gadu: 0
    Windows XPFirefox

Re: Wątki - problem z klasą nie będącą formą

Nowy postprzez Corvis » piątek, 19 marca 2010, 11:39

Ten kod tak jak mówiłem jest kodem testowym, stąd wszystko jest public, nazwy i formatowanie leży - niechciałem się bawić, tylko potestować swoje pomysły. Przerobiłem to tak, że działa bez błędów. Teraz polukam na twoje uwagi i postaram się to zrobić tak, żeby już nie było żadnych problemów z tym.
Nie masz wystarczających uprawnień, aby zobaczyć pliki załączone do tego postu.
"Sukcesy trwają, dopóki ich ktoś nie spieprzy. Porażki są wieczne"

Dr Gregory House
Avatar użytkownika
Corvis
Programista I
Programista I
 
Posty: 880
Dołączył(a): sobota, 26 lipca 2008, 00:31
Podziękował : 80
Otrzymał podziękowań: 30
System operacyjny: WINDOWS 7 64-bity
Kompilator: Praca - C++ Builder XE2 ENTERPRISE - Update 4, Dom - C++ Builder XE4 - Uddate 1
Gadu Gadu: 0
    Windows VistaSafari

Re: Wątki - problem z klasą nie będącą formą

Nowy postprzez Cyfrowy Baron » piątek, 19 marca 2010, 11:46

W tej funkcji zabrakło odświeżania grafiki: this->Invalidate().

Kod: Zaznacz cały
void test::Maluj() {
    if(flgMalowanie==1) return;
    flgMalowanie=1;

    bitmapa->Width = this->Width;
    bitmapa->Height = this->Height;

    bitmapa->Canvas->Brush->Color = clBlack;               
    bitmapa
->Canvas->Pen->Color = clBlack;
    bitmapa->Canvas->Pen->Style = psSolid;
    bitmapa->Canvas->Rectangle(0, 0, bitmapa->Width, bitmapa->Height);

    int i = 30; 
    while
(i!=0) {
        bitmapa->Canvas->Pen->Color = clRed;
        bitmapa->Canvas->Rectangle(10+i,10+i,20+i,20+i);
        Sleep(100);
        i--;
        this->Invalidate();
    }
    
    flgMalowanie
=0;
    MoznaKopiowac = true;


Poza tym, Tój program u mnie działa bezbłędnie.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: Wątki - problem z klasą nie będącą formą

Nowy postprzez polymorphism » piątek, 19 marca 2010, 11:50

Kod: Zaznacz cały
int __fastcall test::Obliczenia(Pointer Parameter) 
{
    (...)

    ExitThread(GetExitCodeThread(Obliczenia,0));
    return 1; 
} 

Dodanie return absurdalności tej konstrukcji nie ujmuje 8-) Jeszcze raz napiszę: zajrzyj do dokumentacji, przeczytaj o GetExitCodeThread, kiedy się tę funkcję wywołuje i, co najważniejsze, w jakim celu. To samo z ExitThread. Jaki jest sens wywoływania tej funkcji tuż przed zakończeniem wątka?
C++ Reference - opis wszystkich klas STL-a i funkcji C.
Avatar użytkownika
polymorphism
Doświadczony Programista ● Moderator
Doświadczony Programista ● Moderator
 
Posty: 2156
Dołączył(a): piątek, 19 grudnia 2008, 13:04
Podziękował : 0
Otrzymał podziękowań: 200
System operacyjny: Windows 8.1
Windows 10
Linux Mint 21.1
Kompilator: Visual Studio
Visual Studio Code
MSYS2 (MinGW, clang)
g++
clang
Gadu Gadu: 0
    Windows XPFirefox

Re: Wątki - problem z klasą nie będącą formą

Nowy postprzez Corvis » piątek, 19 marca 2010, 11:57

polymorphism - Kod odnośnie wątków skopiowałem z serwisu cb - nie analizowałem go. Na tą chwilę miałem problem z wywalaniem się aplikacji. Pomogło :

Kod: Zaznacz cały
bitmapa->Cavas->Lock() ;
// (...)
bitmapa->Cavas->Unlock();


Teraz zajmę się resztą - dzięki za uwagi odnośnie synchronizacji.

Baronie dodanie :

Kod: Zaznacz cały
this->Invalidate();


powoduje u mnie, że raz obraz widać raz nie ;) - ale dojde o co tu chodzi
"Sukcesy trwają, dopóki ich ktoś nie spieprzy. Porażki są wieczne"

Dr Gregory House
Avatar użytkownika
Corvis
Programista I
Programista I
 
Posty: 880
Dołączył(a): sobota, 26 lipca 2008, 00:31
Podziękował : 80
Otrzymał podziękowań: 30
System operacyjny: WINDOWS 7 64-bity
Kompilator: Praca - C++ Builder XE2 ENTERPRISE - Update 4, Dom - C++ Builder XE4 - Uddate 1
Gadu Gadu: 0
    Windows VistaSafari

Re: Wątki - problem z klasą nie będącą formą

Nowy postprzez Cyfrowy Baron » piątek, 19 marca 2010, 12:07

Ale bez tego grafika nie będzie odświeżana automatycznie. Jak pisałem wcześniej GDI+ jest lepszym rozwiązaniem.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: Wątki - problem z klasą nie będącą formą

Nowy postprzez Cyfrowy Baron » piątek, 19 marca 2010, 12:57

Te kombinacje z wątkiem nie maja dla mnie trochę sensu. Inicjujesz wątek w konstruktorze klasy, potem kończysz jego działanie niezależnie od tego, czy jest to akurat potrzebne. Wątek zostaje uruchomiony w momencie utworzenia obiektu klasy, i zaczyna działać niezależnie od tego czy jest potrzebny czy nie. Kończysz działanie wątku nie sprawdzając czy będzie jeszcze potrzebny i niezależnie od tego czy wykonał zadanie czy nie. Ponieważ tworzysz wątek w konstruktorze klasy to po zakończeniu jego działanie nie masz możliwości ponownego uruchomienia wątku.

Skoro tworzysz watek w konstruktorze klasy to powinieneś go kończyć w destruktorze, za pomocą funkcji TerminateThread.

Poczytaj:
http://mediawiki.ilab.pl/images/5/5d/Sop_09_lab.pdf
http://www.wsaiz.pl/dydaktyka/mmatusiew ... watkow.doc
http://cpw.net.pl/c++/faq/268/
http://forum.ddt.pl/?Tid=913
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: Wątki - problem z klasą nie będącą formą

Nowy postprzez Corvis » piątek, 19 marca 2010, 13:07

Idea jest taka, że:

1 ) Mam klase która maluje ( dokładnie wykresy )
2 ) Klasa malująca wykresy po utworzeniu -> uruchamia wątek
3 ) Wątek działa jak Zegar ( stąd ta pętla while ) -> ale funkcja Malowanie ma się wykonać dopiero po ustawieniu odpowiedniej flagi ( w tym przykłądzie co dałem : Namaluj )
4 ) W trakcie zwalniania klasy głównej -> niszczony jest też wątek.

Dzięki za materiały, jak skończe pisać to podeśle *.exe to zobaczycie o co mi chodziło :)
"Sukcesy trwają, dopóki ich ktoś nie spieprzy. Porażki są wieczne"

Dr Gregory House
Avatar użytkownika
Corvis
Programista I
Programista I
 
Posty: 880
Dołączył(a): sobota, 26 lipca 2008, 00:31
Podziękował : 80
Otrzymał podziękowań: 30
System operacyjny: WINDOWS 7 64-bity
Kompilator: Praca - C++ Builder XE2 ENTERPRISE - Update 4, Dom - C++ Builder XE4 - Uddate 1
Gadu Gadu: 0
    Windows VistaSafari

Następna strona

  • Podobne tematy
    Odpowiedzi
    Wyświetlone
    Ostatni post

Powrót do Ogólne problemy z programowaniem

Kto przegląda forum

Użytkownicy przeglądający ten dział: Brak zalogowanych użytkowników i 4 gości