• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

zegarek w programach czyli dlaczego to nie jest idealne

VPS Starter Arubacloud
0 głosów
281 wizyt
pytanie zadane 4 stycznia 2017 w C i C++ przez military Obywatel (1,120 p.)
Jak mamy komponent timer to zazwyczaj ma funkcję tick albo cos takiego. Ok i ustawmy interwał na 1000 czyli sekunda. I do tej funkcji wpisujemy jakieś linie kodu. I tutaj jest problem, żeby wykonać te operacje potrzeba czasu, fakt, dzisiaj to trwa tak krótko ze... No nic nie trwa. Ale powiedzmy sto miliardów tików i.... No właśnie... Mamy desynchronizację z prawidłowym czasem. Jak temu zapobiegać i wgl. Ktoś ma jakiś pomysł?? Trochę kreatywności. Mój pomysł jest taki żeby zmierzyć czas ile trwają te operacje i odjąć ten czas od interwału i mamy po problemie.

2 odpowiedzi

+2 głosów
odpowiedź 4 stycznia 2017 przez draghan VIP (106,230 p.)
wybrane 4 stycznia 2017 przez military
 
Najlepsza

Trochę rozdmuchany ten Twój problem. Funkcje wywoływane co interwał czasu (oparte na timerach) w bibliotekach powinny być implementowane w oparciu o przerwania czasowe. Czyli nie powinno w ogóle tam być mechanizmu zliczającego czas dopiero w zależności od zakończenia wykonania Twoich instrukcji (natomiast jak jest w praktyce...? Jeśli Twoje biblioteki są open-source, możesz pokusić się o sprawdzenie; jeśli nie są otwartoźródłowe, poszukaj w dokumentacji lub zapytaj twórców).
Poprawnie zaimplementowany mechanizm timerów to taki który dokładnie co zadany interwał ma wywoływać Twoją funkcję. Takie rozwiązanie jest niezależne od czasu wykonania Twojego kodu, bo przerwania są zdarzeniami zewnętrznymi w stosunku do programu.

Przy programowaniu mikrokontrolerów bardzo złą praktyką jest umieszczanie dużego bloku kodu w funkcji obsługi przerwania. Dla przerwań czasowych zazwyczaj cała funkcja to tylko inkrementacja zmiennej (co zajmuje jeden cykl procesora), zaś rzeczywiste operacje związane z tym interwałem realizowane są w torze głównym programu, w oparciu właśnie o tę inkrementowaną zmienną.

A z drugiej strony - jeśli chcesz mieć tylko dokładny czas, to nie kombinuj ze zliczaniem "ticków". Po prostu pobierz czas systemowy. I tu znów zależy jakich używasz bibliotek, ale sporo z nich posiada zaimplementowane funkcje do obsługi zegara systemowego - z różną dokładnością. Standard C++ jest całkiem rozbudowany w tej kwestii. Dokładniej nie będzie. :)

komentarz 4 stycznia 2017 przez military Obywatel (1,120 p.)
No tak ale załóżmy ze operacje trwają 0.0000000001 sekundy i ten czas powinien być automatycznie zmniejszony interwał
komentarz 4 stycznia 2017 przez draghan VIP (106,230 p.)
Chyba nadal nie rozumiesz - czas między przerwaniami zliczany jest niezależnie od wykonanych operacji.
komentarz 4 stycznia 2017 przez military Obywatel (1,120 p.)
nadal nie rozumiem
komentarz 4 stycznia 2017 przez draghan VIP (106,230 p.)

Jeśli timery są dobrze zrobione, to wyglądają w taki sposób:

Niebieskie prostokąty to wykonanie kodu, podpiętego do timera. Czerwone piki to przerwanie timera, czyli impuls do wywołania Twojej funkcji - pomiędzy jednym a drugim impulsem upłynie zawsze czas Δt, niezależnie od czasu wykonania niebieskich bloczków.

Czas Δt jest liczony od poprzedniego czerwonego piku, nie zaś od końca niebieskiego bloczka. Prościej chyba nie potrafię.

komentarz 4 stycznia 2017 przez military Obywatel (1,120 p.)
aaa... a co jak to niebieskie przekroczy długość tego zakresu??
komentarz 4 stycznia 2017 przez draghan VIP (106,230 p.)
Wtedy jest źle. :) Nie należy dopuszczać do powstania takiej sytuacji.

Wszystko zależy, jak programista to rozwiąże: jakie ma możliwości implementacyjne oraz jakie rozwiązanie jest wystarczające na potrzeby budowanego systemu.

W najprostszym przypadku funkcja zostanie wywołana ponownie.
Jeśli owa funkcja tworzy nowy wątek, to może się zazębiać z wywołaną poprzednio - to może prowadzić do lawinowego wywoływania owej funkcji, co może być groźne dla aplikacji. Rozwiązanie tego problemu jest znów zależne od możliwości implementacyjnych - jaki model wielowątkowości programista przyjmie za obowiązujący (czy blokować kolejne wywołania? Jak i kiedy synchronizować tę funkcję z resztą aplikacji?).
Jeśli owa funkcja nie tworzy nowego wątku, to na wywołanie jej kolejny raz program zaczeka aż kod z pierwszego wywołania się skończy wykonywać. Jeśli takich zbyt długich funkcji będzie więcej, program zacznie być nieresponsywny.

Jeśli wiadome jest, że kod wywoływany cyklicznie ma tendencję do przekraczania dopuszczalnego czasu trwania, to można pokusić się o mechanizm niedopuszczający do lawinowego wywoływania - opuszczający niektóre kolidujące wywołania, być może z późniejszym nadganianiem, jeśli tego wymaga sytuacja i jest ku temu sposobność.

Jak widzisz, bardzo wiele "jeśli" się tu pojawia - nie jest to tak banalna sprawa. Na pewno i tak nie wyczerpałem wszystkich możliwości. :)

Naprawdę najprostszym rozwiązaniem jest zgrubne oszacowanie czasu trwania kodu naszej funkcji i dobrania odpowiedniego interwału, który nie jest zbyt krótki dla funkcji.
komentarz 4 stycznia 2017 przez military Obywatel (1,120 p.)
ok masz to naj a jak oszacować ile będzie trwał nasz fragment kodu??
komentarz 4 stycznia 2017 przez draghan VIP (106,230 p.)
Na oko albo zmierzyć. :) Operacje wejścia/wyjścia zawsze zajmują sporo czasu procesora, duże pętle też swoje robią.

Trzeba trochę zdrowego rozsądku - jeśli masz do odczytania jakiś duży plik, to nie można wymagać tego co trzy milisekundy. ;)
komentarz 4 stycznia 2017 przez military Obywatel (1,120 p.)
no ok dzięki za pomoc :)
+2 głosów
odpowiedź 4 stycznia 2017 przez maly Nałogowiec (37,190 p.)
Jeśli mówisz o Builderze to do obsługi czasu służy TDateTime.

Kontrolka TTimer jest na tyle nie dokładna że desynchronizację masz już na starcie, metoda OnTimer wywoływana jest nie co ustalony czas tylko nie wcześniej niż ustalony czas.
komentarz 4 stycznia 2017 przez military Obywatel (1,120 p.)
Czyli może nawet i po 2 sekundach??
komentarz 4 stycznia 2017 przez maly Nałogowiec (37,190 p.)
Przy dużym obciążeniu głównego wątku aplikacji może nawet dłużej.
komentarz 4 stycznia 2017 przez military Obywatel (1,120 p.)
jak??
komentarz 4 stycznia 2017 przez maly Nałogowiec (37,190 p.)

Co jak? Jak długo?
Daj sobie na formatkę timer z metodą OnTimer, buttona z metodą OnClick i labela, zobaczysz że po kliknięciu w buttona timer się nie wywołuje.

int a = 0;

void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
    Label1->Caption = a++;
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Button1Click(TObject *Sender)
{
	for(int i = 0;i < 100000000; ++i)
		Caption = i;
}

 

Podobne pytania

0 głosów
1 odpowiedź 200 wizyt
0 głosów
1 odpowiedź 156 wizyt
+1 głos
3 odpowiedzi 250 wizyt
pytanie zadane 22 sierpnia 2015 w PHP przez inny_sub Obywatel (1,120 p.)

92,452 zapytań

141,262 odpowiedzi

319,077 komentarzy

61,854 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Akademia Sekuraka 2024 zapewnia dostęp do minimum 15 szkoleń online z bezpieczeństwa IT oraz dostęp także do materiałów z edycji Sekurak Academy z roku 2023!

Przy zakupie możecie skorzystać z kodu: pasja-akademia - użyjcie go w koszyku, a uzyskacie rabat -30% na bilety w wersji "Standard"! Więcej informacji na temat akademii 2024 znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...