logo elektroda
logo elektroda
X
logo elektroda
REKLAMA
REKLAMA
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

Delphi: Błąd Canvas does not allow drawing przy rysowaniu w wątkach

leburaque 21 Lut 2012 17:49 2125 5
REKLAMA
  • #1 10578284
    leburaque
    Poziom 17  
    Posty: 488
    Pomógł: 4
    Ocena: 111
    Witam! Podczas poruszania tematu ilości optymalnych wątków dla programu (tutaj: https://www.elektroda.pl/rtvforum/topic2205517.html#10570584) "wyskoczył" pewien problem z którym nie mogę się uporać.

    W programie obliczenia wykonuje kilka wątków, wyniki chciałbym rysować na bieżąco na Canvas mojej formy głównej.

    Niestety, po jakimś czasie pracy programu kompilator wywala następujący błąd: Canvas does not allow drawing'. Zgłaszający wątek zawiesza się (właściwie to zgłasza OnTerminate, które przejąłem), pozostałe kontynuują pracę. Znów po losowym obiegu sytuacja się powtarza, aż wszystkie wątki się zawieszą.

    Kompilator kolejno wskazuje na wszystko co wykorzystuje Canvas (wykreślałem linijki kodu, żeby sprawdzić z czym może to mieć związek), np.:
    Kod: Delphi
    Zaloguj się, aby zobaczyć kod


    Procedurę rysowania wywoływałem poprzez TThread.Synchronize, ale wówczas kompilator zgłasza mi błąd: Project raised exception class EAccessViolation with message 'access violation in module at adress...

    Oto przykład wywołania z tablicy wątków:

    Kod: Delphi
    Zaloguj się, aby zobaczyć kod


    Czy to może być kwestia mojej deklaracji, czy tego, że nie można rysować wątkami na Formie? Wkleić kompletny kod?
  • REKLAMA
  • #2 10578624
    LED5W
    Poziom 34  
    Posty: 2302
    Pomógł: 264
    Ocena: 162
    Odnośnie Synchronize musiałby się wypowiedzieć ktoś znający Delphi.

    Procedurę rysowania na wywoływałbym z procedury rysowania okna. Z "roboczego" wątku wywołać Invalidate/InvalidateRect (nazwy z WinAPI ;)).
  • REKLAMA
  • Pomocny post
    #3 10578792
    Dżyszla
    Poziom 42  
    Posty: 7077
    Pomógł: 1095
    Ocena: 226
    Użyj przed rysowaniem Lock dla kanwy, a po rysowaniu uwolnij ją.

    Co do Synchronize - musi ona być wywoływana zawsze z danego wątku, a ten zapis co przedstawiłeś nie do końca wskazuje na to.
  • REKLAMA
  • #4 10579732
    leburaque
    Poziom 17  
    Posty: 488
    Pomógł: 4
    Ocena: 111
    Użyłem tego tak:

    Kod: Delphi
    Zaloguj się, aby zobaczyć kod


    I to zadziałało, rysuje się piknie panocku, ale podczas rysowania w efekcie mam nieaktywne np. menu z poziomu którego steruję programem. Cała forma robi się nieaktywna... chyba, że podczas pracy programu na chwilę przejdę do innego programu, debbugera, albo formy, wówczas forma odzyskuje władzę.

    Podejrzewam, że to coś u mnie sprzętowego. Tak czy siak - działa. Bardzo dziękuję.

    Tablicę wątków złożyłem taką:

    Kod: Delphi
    Zaloguj się, aby zobaczyć kod


    ale odkąd wykorzystałem Lock/Unlock nie wywołuję już tej procedury

    Kod: Delphi
    Zaloguj się, aby zobaczyć kod

    poprzez Synchronize, tylko bezpośrednio w wątku. I pięknie działa.

    Tak na wszelki wypadek zapytam - czy popełniłem niniejszym jakieś błędy techniczne na które mogę być potem narażony?

    Dodano po 6 [minuty]:

    I od razu o coś spytam. Czy kiedy tworzę obraz większy niż Canvas mojej formy, to mogę go potem jakoś przewijać w formie? Czy raczej powinienem poszukać obiektu, który postawię na formie i jego obsługą się zajmę?
  • REKLAMA
  • #5 10585827
    leburaque
    Poziom 17  
    Posty: 488
    Pomógł: 4
    Ocena: 111
    OK, w sumie to by było na tyle:).

    Temat do zamknięcia, dziękuję za pomoc.
  • #6 10586238
    arnoldziq
    VIP Zasłużony dla elektroda
    Posty: 5376
    Pomógł: 789
    Ocena: 300
    Pozwolę sobie jeszcze poruszyć, na koniec, dość istotną sprawę.
    Nie do końca opisałeś, co i jak rysujesz, ale podejrzewam, że blokujesz canvas przy każdym wywołaniu synchronize.
    Zastanów się, czy to ma sens, i czy musisz koniecznie rysować coś i czy będzie za każdym razem to taka zmiana, która będzie widać.
    W zależności od ilości wątków, blokuj canvas i rysuj co któreś wywołanie synchronize. Co 10, co 100... zależy jakie będą różnice w tym "rysunku".
    To przyspieszy wykonanie wątków drastycznie.
    Pozdrawiam i powodzenia. Arnoldziq.
REKLAMA