Elektroda.pl
Elektroda.pl
X
Proszę, dodaj wyjątek www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

C++ - Błąd przy próbie uruchomienia wątku

Grzecho83 30 Sie 2013 23:31 1524 5
  • #1 30 Sie 2013 23:31
    Grzecho83
    Poziom 9  

    Witam, próbuję przerobić swój program aby wykorzystywał wątki, nie robiłem tego wcześniej dlatego posiłkuję się tym kursem:
    Wątki
    Niestety nie działa i nie wiem dlaczego. Napisałem taką funkcję:

    Kod: cpp
    Zaloguj się, aby zobaczyć kod

    funkcję próbuje wywołać w ten sposób:
    Kod: cpp
    Zaloguj się, aby zobaczyć kod

    i niestety wyskakuje błąd przy kompilacji w linii "HANDLE hThread......." o treści :
    Kod: text
    Zaloguj się, aby zobaczyć kod

    Niestety nie rozumiem tego komunikatu, może to wynika z tego że w przykładzie jest program na konsolę a ja mam okienka, i może w definicji klasy coś trzeba dopisać, ale to tylko takie moje przypuszczenia. Problemem może być też konwencja "__cdecl", nie bardzo rozumiem o co w tym chodzi. Nie wiem jak to ugryźć. Będę wdzięczny za pomoc.
    Pozdrawiam, Grzegorz.

    0 5
  • Pomocny post
    #2 31 Sie 2013 10:54
    przemko07
    Poziom 15  

    zamiast funkcji

    Kod: cpp
    Zaloguj się, aby zobaczyć kod

    musisz miec
    Kod: cpp
    Zaloguj się, aby zobaczyć kod


    void* to nie to samo co void.
    void oznacza brak, void* oznacza wskaznik na cokolwiek.
    void ma 0 bajtów
    void* ma rozmiar int (czasami bedzie 4 bajty czasami 8 bajtow)
    void* to sposób wskazników który nie ogranicza Cie w typach,
    może on wskazywać na cokolwiek. przykład
    Kod: cpp
    Zaloguj się, aby zobaczyć kod

    i w ten sposób nasza tablica nie ma 2 elementow, tylko 8

    dzieki temu mozesz wysylac obiekty jako argumenty do funkcji, bo jak zauwazysz moze byc tylko jeden argument funkcji i jesli chcesz wyslac naprzyklad
    Kod: cpp
    Zaloguj się, aby zobaczyć kod

    to musisz to obudowac w klase, a potem wyslac wskaznik na obiekt tej klasy.

    __fastcall, __cdecl i z 10 innych to konwencje wywołań.
    czyli sposobu ustawienia ramki argumentów na stosie. różne konwencje różnie układają argumenty na stosie, jedne układają od lewej do prawej drógie na odwrót. inne zmuszają aby wywołujący zajmował się stosem drugie wywoływany.
    jeśli masz funkje w dll i znasz jej konwencje wywołań to z poziomu assemblera możesz samemu na stos powkładać argumenty w odpowiedniej kolejności i wysłać adres funkcji do rejestru.
    najnowsze gcc dla C++ wsadza wszędzie __cdecl,
    ogólnie nie trzeba się martwić o to bo to przeszkadza tylko gdy zaczynamy tworzyć własne .dll i współdzielić je z innymi językami (C# domyślie nie używa __cdecl i można się nieźle zdziwić że nam funkcja się wywołuje porawnie ale błąd jest w return)

    0
  • #3 31 Sie 2013 15:57
    Grzecho83
    Poziom 9  

    Dzięki za wyczerpujące wyjaśnienie, niestety w ten sposób już próbowałem i wyskakiwał taki sam błąd, w definicji klasy też zmieniłem na

    Kod: cpp
    Zaloguj się, aby zobaczyć kod

    a może to klasy się jakoś inaczej definiuje jeśli chcę korzystać z wątków, w przykładzie z kursu był program na konsolę bez klasy więc nie mam porównania.

    A tak na marginesie mam jeszcze jedno pytanie, funkcja o której mówimy steruje silnikiem krokowym przez port LPT (zapala i gasi jeden pin portu), niestety nie działa płynnie, jeśli komputer jest zajęty to silnik zatrzymuje się na ułamek sekundy, a kiedy robię coś z okienkiem programu (przesuwam, minimalizuje) to całkiem się wstrzymuje. I mam nadzieje że jeśli wywołam tą funkcję w wątku to problem zniknie. Powiedzcie czy to zadziała czy może niepotrzebnie się męczę z tym.

    0
  • Pomocny post
    #4 31 Sie 2013 16:56
    przemko07
    Poziom 15  

    1) spoko, szkoda że nie działa

    2) no akurat to najważniejsza rzecz, gdy funkcja od metody różni się trochę. metoda jako pierwszy argument dostaje wskaźnik na obiekt this to niejawny argument, nie widać go.
    Nie da się stworzyć metody bez argumentów.
    Każda funkcja która jako pierwszy argument ma wskaźnik na obiekt może być nazywana metodą. dopisanie static powinno usunąć ten niejawny argument.

    3) z pewnością pomorze, na pewno nie pogorszy pracy. od początku zauważysz że zżera cały rdzeń, ja to rozwiązuje w taki sposób że używam Sleep(unsigned int) gdzie wartość jest w milisekundach. czas dopasuj sobie wedle uznania. Jeszcze na jedną rzecz zwrócę uwage, nie twórz w wątkach takich pętli

    Kod: c
    Zaloguj się, aby zobaczyć kod


    niech to zawsze będzie z użyciem jakiejś zmiennej boolowskiej którą ustawisz na false na przykład podczas zamykania aplikacji. Niektórzy powiedzą że niepotrzebna taka zabawa, bo wątki należą cały czas do procesu nadrzędnego i jak się zamknie aplikacjie to i wątek się zamyka, ale to często jest z pewnym opóźnieniem nawet sięgającym sekundy, mimo iż aplikacja została wyłączona to wątek dalej pracuje, a jeśli to ma być program sterujący urządzeniem zewnętrzny to nie może się tak zdarzyć aby po wyłączeniu programu urządzenie wykonywało swoją prace, nawet na 100 ms.

    0
  • Pomocny post
    #5 31 Sie 2013 17:19
    krru
    Poziom 32  

    Nie możesz w ten sposób uruchamiać metody klasy (no chyba że statyczną). beginthread wymaga normalnej funkcji a nie metody.
    Wskaźnik do obiektu klasu możesz przekazać jako Args.

    0
  • #6 31 Sie 2013 18:18
    Grzecho83
    Poziom 9  

    Dzięki, udało się kiedy zdefiniowałem funkcję poza klasą, niestety nie widać poprawy, czy w wątku głównym czy osobno, silnik nie chodzi płynnie. Problem w tym że między jednym impulsem a drugim musi upłynąć określona ilość czasu, jeśli procesor dostanie w między czasie parę zadań odstęp się zmieni.
    Czas nauczyć się komunikacji atmega8 z komputerem, najlepiej przez usb i przenieść sterowanie na mikrokontroler, komputer będzie jedynie wysyłał rozkazy.
    Niemniej jednak dzięki wielkie za pomoc.

    0