2009-06-06 12 views
6

Istnieje kilka wątków w mojej aplikacji, które działają w tle. Łączą się z bazą danych i wykonują czasochłonne zapytania wybrane. W większości przypadków zapytania te zwracają tylko kilka rekordów. Od czasu do czasu mogą jednak zwrócić dziesiątki tysięcy rekordów. Wszystkie te są następnie przetwarzane w pętli.Delphi - dostosowanie czasu snu wątku

Ponieważ taka sytuacja może wystąpić w kilku wątkach w tym samym czasie, nie chcę, aby moja aplikacja wykorzystała 100% czasu procesora, gdy te wątki przetwarzają dane; nie chcę też, aby wszystkie wątki walczyły o czas procesora. Dlatego nazywam funkcję Sleep() w każdej iteracji pętli w tych wątkach.

Nie wiem jednak, jak ustawić czas snu. Nie chcę, aby pętle trwały wiecznie, więc okres snu nie może być zbyt długi. Ustawiłem go na 2 milisekundy w każdej iteracji (w każdym wątku) (dlaczego 2ms? - to dobre pytanie :)).

Z drugiej strony myślałem, że mogę wydłużyć czas snu, ale wywołać uśpienie tylko raz w każdej iteracji (powiedzmy, Sleep (100) co 50 iteracji). Jakie podejście powinienem wybrać? Jedna część pętli trwa około 30 ms (bez żadnych uśpień).

Prosimy o radę.

Dzięki!
Mariusz.

Odpowiedz

9

Wywołanie Tryb uśpienia() nie ma sensu. Wykorzystaj całą moc obliczeniową, jaką możesz uzyskać, i pozwól systemowi opracować najlepszy sposób planowania wątków. Wywołanie Sleep() spowoduje tylko dodatkowe przełączniki kontekstu i obniży przepustowość. Jeśli przetwarzanie w tle zakłóca działanie głównego wątku lub innych aplikacji, należy odpowiednio obniżyć priorytet wątków tła.

Jeśli chcesz pozwolić wątkom spać, aby ograniczyć ilość danych, które generują dla konsumentów, zajrzyj do kolejek producent-konsument. Niech wątki producenta po prostu blokują się, gdy ich kolejka jest pełna, w ten sposób nie będziesz potrzebował w ogóle bawić się z timingiem.

Należy również pamiętać, że używanie maksymalnego procesora jest ogólnie rzecz biorąc dobrą rzeczą, szczególnie w przypadku nowoczesnych procesorów. Nawet na laptopach, które mają krótki czas dużego obciążenia, jest lepsze niż sztuczne wydłużanie czasu potrzebnego na zadanie, ponieważ procesor/cały system szybciej będzie mógł wejść w niższe stany zasilania.

+0

Ale jeśli ten działa w tle na komputerze, na którym również pracuje na kogoś (np napisanie arkusza kalkulacyjnego), nie chcą, aby proces w tle spowodował, że proces pierwszego planu stał się bezużyteczny. – dummzeuch

+2

To prawda, ale właśnie dlatego napisałem, że priorytet wątku tła można obniżyć, pozostawiając inne aplikacje (lub główny wątek) responsywnymi, jednocześnie wykorzystując pełen potencjał systemu. W nowoczesnych (wielordzeniowych) systemach utrzymanie wszystkich rdzeni dostatecznie obciążonych jest znacznie większym problemem niż brak reaktywności pierwszoplanowej aplikacji. I masywne niezoptymalizowane operacje wejścia/wyjścia są znacznie większym zagrożeniem dla użyteczności systemu niż wysokie obciążenie procesora. – mghie

2

Może istnieć lepsze podejście niż używanie snu do kontrolowania wątków. Ponieważ wywołanie bazy danych może zwrócić 1-1000 rekordów do przetworzenia, może być sens oddzielenie aplikacji na dwie warstwy, może za pomocą kolejki komunikatów w celu buforowania żądań. Twoja aplikacja może odwołać się do usługi danych, a usługa danych uruchomi następnie zapytanie i wyśle ​​poszczególne wiadomości danych (lub bloki wiadomości itp.) Do kolejki. Twoja aplikacja może następnie utworzyć tyle wątków, które są odpowiednie do przetwarzania wiadomości. Więcej wątków oznacza szybsze przetwarzanie kosztem procesora, ale możesz to zmienić, aby uzyskać właściwą równowagę.

3

Lepiej po prostu stwórz wątki o niskim priorytecie i pozwól im pracować bez snu, w przeciwnym razie nie użyjesz pełnej mocy procesora. Na przykład w systemach multi-core/multi-cpu. Lub jeśli twój system jest w 100% bezczynny: po co czekać lub spać?

Ale jeśli potrzebujesz trochę snu, pamiętaj, że sen (1) czeka 10-15ms (!) Z powodu domyślnego timeslasu Windows. Możesz użyć timeBeginPeriod (1) jednostki MMSystem.pas, aby ustawić rozdzielczość na 1ms :-) (użyłem tego do komunikacji szeregowej).

0

użyć TThread.Sleep() z System.Classes, zamiast Sleep() z WinApi.Okna

// Winapi.Windows contains GetTickCount and Sleep 
// System.Classes contains TThread (universal option) // TThread.GetTickCount() // TThread.Sleep() 
uses System.Types, System.Classes, Vcl.Forms; 

// następnie w procesie użyć następujących

TThread.Sleep(0); 

Application.ProcessMessages(); // clear all Vcl messages // part of Vcl.Forms 
CheckSynchronize(); // check all threaded events 
Powiązane problemy