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.

[API] [C++] użycie Timera i pętle

puntigamer 24 Wrz 2009 02:47 2307 8
  • #1 24 Wrz 2009 02:47
    puntigamer
    Poziom 13  

    mam tablice danych np [8][10]. chce pobierac za każdym razem jednorazowo jeden wiersz, wykonac na danych z tego wiersza pewne działania (zajmie mi to nawet 5 sekund), uruchomic Timer na wartosc czasową, którą wyliczę. Czas na jaki chce się tu zatrzyamc powinien wlasnie byc odmierzany w Timerze.
    Następnie po przepełnieniu Timera (przykladowo te 5 sek) chciałbym jakoś wrócić do wykonywania funkcji odpowiedzialnej za czytanie nastepnego wiersza z tabeli.

    macie jakieś pomysły? Chcę zastosować SetTimer, KillTimer, ale jakoś nie mogę rozłożyć, co gdzie wykonać. a przede wszystkim jak wrócić z obsługi przepełnienia Timera (czyli z OnTimer) do pętli (następnego wiersza...)

    pozdr

    0 8
  • #2 24 Wrz 2009 04:46
    qbus1981
    Poziom 11  

    Kiedyś programowałem w WinApi i szło to jakoś tak:
    Na początku zdefiniuj sobie timer tak:
    #define IDT_TIMER1 1001
    w trakcie programu po stworzeniu okna najlepiej wywołujesz pierwszy timer:
    unsigned int czas = rand() % 10 + 25; // czas od 10 do 35 sek
    SetTimer(hWnd,IDT_TIMER1,czas,TIMERPROC(NULL)); // tworzymy nowy timer
    Nastepnie w procedurze obsługi komunikatów okna obsługujemy wywołania TIMERA:

    case WM_TIMER:
    switch (wParam)
    {
    case IDT_TIMER1: // nasz timer
    {
    // tu co tylko chcesz
    unsigned int czas = rand() % 10 + 25; // czas od 10 do 35 sek
    KillTimer(hDlg,IDT_TIMER1); // zabijamy stary timer
    SetTimer(hDlg,IDT_TIMER1,czas,TIMERPROC(NULL)); // tworzymy nowy o tym samym ID co stary
    }break;

    Co do powrotu to nie lepiej stworzyć sobie funkcję i do niej wracać z wywołania timera ?

    EDIT

    Jeśli chcesz tylko zatrzymać program na parę sekund bez wykonywania instrukcji to może łatwiej będzie zastosować :
    Sleep(milisekundy);

    0
  • #3 24 Wrz 2009 07:42
    jestam
    Specjalista Automatyk

    Aplikacja okienkowa czy konsolowa?
    Jeżeli okienkowa to gdzie wykonujesz obliczenia? W osobnym wątku?

    0
  • #4 25 Wrz 2009 03:01
    puntigamer
    Poziom 13  

    Okna. Obliczenia będą wykonywane w zewn funkcji. za każdym razem jeden wiersz i uruchamianie timera na określobny czas, po którym to czasie w wywolaniu timera wracamy do funkcji obliczalacej nastepny wiersz. do tego zmienna globalna okreslajaca numer wiersza nad ktorym pracujemy oraz liczbe wszystkich wierszy.
    Wątki nie są mi na ten czas potrzebne. Obliczen nie jest duzo, a między są inne timery :)
    Czy sądzicie ze to "wyda"?
    Dzięki

    0
  • #5 25 Wrz 2009 08:20
    jestam
    Specjalista Automatyk

    Ta zewnętrzna funkcja będzie uruchamianie np. po kliknięciu przycisku?
    Jeśli tak to potrzebujesz drugiego wątku. Nie wolno zatrzymać wątku w którym przetwarzane są komunikaty okna. A jak już masz drugi wątek to użyj po prostu Sleep().

    Druga opcja, lepsza gdy obliczenia trwają krótko, ale przerwy pomiędzy nimi są konieczne: użyć timera, obsłużyć komunikat WM_TIMER i obliczyć w nim jeden, kolejny wiersz.

    0
  • #6 25 Wrz 2009 13:34
    puntigamer
    Poziom 13  

    Ale jeśli ten przycisk będzie naciskany raz (potem zrobiony na nieaktywny az do zakonczenia przeliczen wszystkich wierszy) tez mogą byc jakies problemy? potem przez wywolanie funkcji bedzie tylko uruchamiana. Nie zatrzymywaloby to chyba wątku komunikatow okna.
    Sleep mnie nie rajcuje bo aplikacja nie może spac, wykonuje sie wiele innych spraw przy okazji.

    Właśnie nie jestem pewien czy obliczac w funkcji (standardowo uruchamianej kliknieciem buttona), czy przy obsluzeniu komunikatu wm_timer

    Dodano po 1 [minuty]:

    Poza tym i tak w funkcji musze wykonac kilka obliczen ktore wylicza czas wymagany do uruchomienia timera i odczekania na pierwszy wiersz. potem inny czas na odczekanie na 2 wiersz... wiec sprawa jest chyba jasne : )

    0
  • #7 25 Wrz 2009 14:21
    jestam
    Specjalista Automatyk

    Ja chyba nie do końca rozumiem o co Ci chodzi. Masz dwie opcje.

    1. Kod obsługujący naciśnięcie przycisku uruchamia dodatkowy wątek, po czym wraca do pętli komunikatów. Dodatkowy wątek czyta dane, oblicza, śpi zadany czas i co tylko chcesz. Zaleta: widać co się dzieje, wada: wymaga synchronizacji dostępu do wspólnych danych - najlepiej jakby wątek pracował na prywatnej kopii danych. Wyniki można przekazywać np. przez PostMessage.

    2. Obliczać w wątku komunikatów okna. Podzielić obliczenia na fragmenty i zapamiętywać ich STAN (jakieś dodatkowe dane informujące co zostało zrobione a co nie) tak aby dało się kontynuować obliczenia tylko na podstawie zapamiętanego stanu. Po kliknięciu przycisku zainicjować stan danymi początkowymi i ustawić timer. W obsłudze WM_TIMER odczytać stan obliczeń, policzyć następny kawałek, zapisać stan, ustawić nowy timer. Zaleta: nie masz dwóch wątków i nie musisz ich synchronizować. Wada: w bardziej złożonych przypadkach (a Twój na taki wygląda) poprawne napisanie tego jest trudne, a późniejsza modyfikacja jeszcze trudniejsza.

    Polecam wersję 1.

    0
  • #8 26 Wrz 2009 01:44
    puntigamer
    Poziom 13  

    Jestem w trakcie pisania czegoś na kształt wersji 2 : )
    Jutro po poludniu znowu zasiądę i dam znać wieczorem. Pozdr

    0
  • #9 02 Paź 2009 00:38
    puntigamer
    Poziom 13  

    No więc w skrócie:
    Po naciśnięciu przycisku START wykonuje się funkcja do niego przypisana.
    W Funkcji tej znamy liczbę wszystkich wierszy i liczbę wierszy "odczytanych" (ta zmienna globalna jest inkrementowana podczas obsługi SetTimer).
    Następnie wyliczam czas oczekiwania i uruchamiam na ten czas licznik. natychmiast wysyłam aktualne informacje o czytanym wierszu przez rs (na tym polega cały chwyt projektu).

    Obsługa Timera:
    Jedynie trzy sprawy. KillTimer, inkrementacja zmiennej globalnej, Wywolanie funkcji obslugujacej przycisk START :)

    Dzięki za pomoc. pozdr

    0