Temat: Pytanie odnośnie tworzenia wątków

Mam pytanie:
Muszę lekko zmodyfikować program napisany w delphi7, a dokładnie umieścić pętlę w wątku by nie blokowała całego programu w trakcie działania.
W związku z tym rodzi się pytanie czy mogę stworzyć wątek w kodzie głównym programu, czy tylko w nowym pliku *pas.
Tomasz Kaczanowski

Tomasz Kaczanowski Ot, programista

Temat: Pytanie odnośnie tworzenia wątków

Miejsce stworzenia wątku w sposób jaki przedstawiłeś nie ma znaczenia. To kwestia jedynie wygody programisty.
Daniel Grabowski

Daniel Grabowski Interaktywne
planowanie produkcji
on-line z MES

Temat: Pytanie odnośnie tworzenia wątków

Za to ma znaczenie, co ten kod w wątku będzie robił.
Pamiętaj, iż VCL nie jest bezpieczny wątkowo i nie możesz np. zmieniać atrybutów kontrolek z kodu uruchamianego w wątku pobocznym (np. zmiana koloru TLabel, ale i też operacja na TDataSet, który jest podpięty do jakiejkolwiek kontrolki wizualnej).
Poza tym, większość komponentów bazo-danowych też bezpieczna, co nie znaczy że nie można korzystać z baz danych w wątkach - oczywiście, że można.
A więc, co ten kod będzie robił?

Temat: Pytanie odnośnie tworzenia wątków

Są to pętle FOR odpowiadające za płynne zaświecenie diód RGB. Każda pętla przypisana jest do odpowiedniej konfiguracji diód np. petla1 -> R, pętla2 -> RG. Cała procedura ma za zadanie płynne włączanie diód: R -> RG -> GB itp. i tak w kółko, aż użytkownik jej nie zatrzyma. Procedurę już napisałem i działa lecz jak ją się uruchomi to wykonywające się pętle blokują działanie programu, blokując również możliwość użytkownikowi jej wyłączenia.

konto usunięte

Temat: Pytanie odnośnie tworzenia wątków

No jest jeszcze alternatywa w postaci instrukcji: Application.ProcessMessages, umieszczonej w pętli. Tyle tylko że w tym przypadku mogą być cyrki tego typu że nie zamknę aplikacji aż do zakończenia pętli czy też jakaś kontrolka zmieni swój stan za wcześnie. Stosowałem z powodzeniem tą instrukcję w pętlach, z tym że należało sprawdzać dodatkowe warunki zakończenia pętli.

Trochę niejasna sprawa dla mnie z tym bezpieczeństwem VCL. Z moich doświadczeń wynika, że najczęściej błędy w aplikacji były spowodowane błędami innych programistów, którzy stworzyli jakieś swoje komponenty.
Daniel Grabowski

Daniel Grabowski Interaktywne
planowanie produkcji
on-line z MES

Temat: Pytanie odnośnie tworzenia wątków

Dariusz Sieńkowski:
Są to pętle FOR odpowiadające za płynne zaświecenie diód RGB.
A ta "dioda RGB", to co to dokładnie jest?
Kontrolka na formie czy dioda w jakimś czymś podłączonym np. do portu COM?
Każda pętla przypisana jest do odpowiedniej konfiguracji diód np. petla1 -> R, pętla2 -> RG. Cała procedura ma za zadanie płynne włączanie diód: R -> RG -> GB itp. i tak w kółko, aż użytkownik jej nie zatrzyma. Procedurę już napisałem i działa lecz jak ją się uruchomi to wykonywające się pętle blokują działanie programu, blokując również możliwość użytkownikowi jej wyłączenia.
OK.
Co to znaczy płynne przełączenie diód?
Dla człowiek płynne to będzie jakieś 25 na sekundę; dla komputera to ślamazarnie wolno.
Możesz pokazać tę pętle?
Ale generalnie tak:
1) Piszesz wątek
2) W metodzie Execute wywołujesz te swoje pętle
3) W pętli dajesz opóźnienie, np. sleep(40);
4) Po opóźnieniu przełączasz diody (wszystko w wątku!), ale sam kod zmieniający kolory wykonujesz za pomocą SYNCHRONIZACJI (TThread.Synchronize)

i to wszystko...
Przy okazji - które Delphi?
Bo od wersji 2010 (nie pamiętam dokładnie czy też nie 2009), możesz napisać tak:


procedure TMyThread.Execute;
begin
while not Terminated do
begin
sleep(40);
Synchronize
(
procedure
begin
if Form.DiodaR.Active then
begin
Form.DiodaR.Active := False;
Form.DiodaG.Active := True;
Form.DiodaB.Active := False;
end
else
if Form.DiodaG.Active then
begin
Form.DiodaR.Active := False;
Form.DiodaG.Active := False;
Form.DiodaB.Active := True;
end
else
if Form.DiodaB.Active then
begin
Form.DiodaR.Active := True;
Form.DiodaG.Active := False;
Form.DiodaB.Active := False;
end;
end
);
end;


W sumie to jest cały kod, bez utworzenia klasy TThread - ale w Delphi robi to automat...
Daniel Grabowski

Daniel Grabowski Interaktywne
planowanie produkcji
on-line z MES

Temat: Pytanie odnośnie tworzenia wątków

Dariusz Rorat:
No jest jeszcze alternatywa w postaci instrukcji: Application.ProcessMessages, umieszczonej w pętli. Tyle tylko że w tym przypadku mogą być cyrki tego typu że nie zamknę aplikacji aż do zakończenia pętli czy też jakaś kontrolka zmieni swój stan za wcześnie. Stosowałem z powodzeniem tą instrukcję w pętlach, z tym że należało sprawdzać dodatkowe warunki zakończenia pętli.
To tak jakbyś napisał, że windows 3.1 miał wielozadaniowość.
Oczywiście, w prostych zastosowaniach - czemu nie; ale alternatywa?
Trochę niejasna sprawa dla mnie z tym bezpieczeństwem VCL. Z moich doświadczeń wynika, że najczęściej błędy w aplikacji były spowodowane błędami innych programistów, którzy stworzyli jakieś swoje komponenty.
No to czas poszerzyć doświadczenia:
http://stackoverflow.com/questions/78475/in-delphi-is-...
I tam masz zestaw linków do poczytania.

konto usunięte

Temat: Pytanie odnośnie tworzenia wątków

Nie wszystko musi być oparte od razu na wątkach. Zresztą z tymi wątkami to nie taka prosta sprawa i mam nawet na to gotowe przykłady. Szczególnie jeżeli kilka wątków odwołuje się do tego samego obiektu VCL. Ale i na to musi znaleźć się rozwiązanie.


{ TMyThread }

TMyThread = class(TThread)
private
FAFinished: boolean;
public
procedure Execute; override;
property AFinished: boolean read FAFinished write FAFinished;
end;

{ TForm1 }

TForm1 = class(TForm)
CountWithoutCritSecButton: TButton;
CountWithCritSecButton: TButton;
Label1: TLabel;
procedure CountWithCritSecButtonClick(Sender: TObject);
procedure CountWithoutCritSecButtonClick(Sender: TObject);
private
public
CriticalSection: TCriticalSection;
Counter: integer;
UseCriticalSection: boolean;
procedure DoCounting;
end;

var
Form1: TForm1;

implementation

{ TForm1 }

procedure TForm1.CountWithCritSecButtonClick(Sender: TObject);
begin
UseCriticalSection:=true;
DoCounting;
end;

procedure TForm1.CountWithoutCritSecButtonClick(Sender: TObject);
begin
UseCriticalSection:=false;
DoCounting;
end;

procedure TForm1.DoCounting;
var
i: Integer;
Threads: array[1..5] of TMyThread;
AllFinished: Boolean;
begin
Counter:=0;

// create the CriticalSection
InitializeCriticalSection(CriticalSection);

// start 5 threads
for i:=Low(Threads) to High(Threads) do
Threads[i]:=TMyThread.Create(false);
// wait till all threads finished
repeat
AllFinished:=true;
for i:=Low(Threads) to High(Threads) do
if not Threads[i].AFinished then AllFinished:=false;
until AllFinished;
// free the threads
for i:=Low(Threads) to High(Threads) do
Threads[i].Free;

// free the CriticalSection
DeleteCriticalSection(CriticalSection);

// show the Counter
Label1.Caption:='Counter='+IntToStr(Counter);
end;

{ TMyThread }

procedure TMyThread.Execute;
var
i: Integer;
CurCounter: LongInt;
j: Integer;
begin
FAFinished:=false;
// increment the counter many times
// Because the other threads are doing the same, it will frequently happen,
// that 2 (or more) threads read the same number, increment it by one and
// write the result back, overwriting the result of the other threads.
for i:=1 to 100000 do begin
if Form1.UseCriticalSection then
EnterCriticalSection(Form1.CriticalSection);
try
CurCounter:=Form1.Counter;
for j:=1 to 1000 do ;
inc(CurCounter);
Form1.Counter:=CurCounter;
finally
if Form1.UseCriticalSection then
LeaveCriticalSection(Form1.CriticalSection);
end;
end;
FAFinished:=true;
end;



To jest przykład w którym wywoływane jest 5 wątków o takim samym działaniu. Jednak użycie CriticalSection a pominięcie tego daje zupełnie inne efekty.

konto usunięte

Temat: Pytanie odnośnie tworzenia wątków

Alternatywą jest TTimer plus własne badanie czasu ostatniej aktualizacji, przy pomocy jednego z:
- QueryPerformanceCounter
- GetTickCount

http://delphi.about.com/od/windowsshellapi/a/delphi-hi...

Sam zegarek TTimer będzie się odpalał z małą dokładnością (55ms ?), ale w połączeniu z powyższym powinno wystarczyć do wizualnych zmian.

Tu dokładniejszy zastępnik:
http://www.programmersheaven.com/download/5874/Downloa...
http://www.sourcecodeonline.com/details/zyltimer.htmlPiotr L. edytował(a) ten post dnia 19.04.12 o godzinie 15:59
Daniel Grabowski

Daniel Grabowski Interaktywne
planowanie produkcji
on-line z MES

Temat: Pytanie odnośnie tworzenia wątków

Dariusz Rorat:
Nie wszystko musi być oparte od razu na wątkach.
Nie musi, ale czasem - powinno.
Generalnie programowanie współbieżne to wyższa szkoła jazdy.
Zresztą z tymi wątkami to nie taka prosta sprawa i mam nawet na to gotowe przykłady.
Szczególnie jeżeli kilka wątków odwołuje się do tego samego obiektu VCL.
Ale i na to musi znaleźć się rozwiązanie.
Podane niżej, to jedno z wielu.
To wcale nie musi być obiekt VCL - to może być dowolny zasób.
To jest przykład w którym wywoływane jest 5 wątków o takim samym działaniu. Jednak użycie
CriticalSection a pominięcie tego daje zupełnie inne efekty.
Pokazałeś nam jedno z rozwiązań problemu synchronizacji wątków przy równoległym dostępie do zasobów w programowaniu współbieżnym.
To samo można osiągnąć za pomocą muteksów lub semaforów.

Poza tym, zamiast stosować kopiuj/wklej bez podania źródła (bo to przecież nie Twój kod) to trzeba było podać link do tego przykładowego modułu z Lazarusa - np. taki:
http://fossies.org/unix/misc/lazarus-0.9.31-36825-2012...
Daniel Grabowski

Daniel Grabowski Interaktywne
planowanie produkcji
on-line z MES

Temat: Pytanie odnośnie tworzenia wątków

Piotr L.:
Alternatywą jest TTimer plus własne badanie czasu ostatniej aktualizacji, przy pomocy jednego z:
- QueryPerformanceCounter
- GetTickCount

http://delphi.about.com/od/windowsshellapi/a/delphi-hi...

Sam zegarek TTimer będzie się odpalał z małą dokładnością (55ms ?), ale w połączeniu z powyższym powinno wystarczyć do wizualnych zmian.
Skąd się wzięło te 55ms?
TTImer to zwykłą nakładka na funkcję WinAPI SetTimer.
Tu dokładniejszy zastępnik:
http://www.programmersheaven.com/download/5874/Downloa...
Staroć bez źródeł.
http://www.sourcecodeonline.com/details/zyltimer.html
Płatny.

A tu bezpłatny i ze źródłami:
http://sergworks.wordpress.com/2010/04/06/a-better-tim...
A takich jest dużo więcej, nawet dostępne w Delphi - polecam zapoznanie się z modułem mmsystem.pas
Przykład:
http://www.swissdelphicenter.ch/torry/showcode.php?id=216

konto usunięte

Temat: Pytanie odnośnie tworzenia wątków

Daniel Wloochacz Grabowski:
Piotr L.:
Alternatywą jest TTimer plus własne badanie czasu ostatniej aktualizacji, przy pomocy jednego z:
- QueryPerformanceCounter
- GetTickCount

http://delphi.about.com/od/windowsshellapi/a/delphi-hi...

Sam zegarek TTimer będzie się odpalał z małą dokładnością (55ms ?), ale w połączeniu z powyższym powinno wystarczyć do wizualnych zmian.
Skąd się wzięło te 55ms?

Na podstawie podanej przeze mnie strony. Dokładna wartość pewnie nie istnieje, bo to jest właśnie cecha TTimer - brak dokładności.
Daniel Grabowski

Daniel Grabowski Interaktywne
planowanie produkcji
on-line z MES

Temat: Pytanie odnośnie tworzenia wątków

Piotr L.:
Daniel Wloochacz Grabowski:
Skąd się wzięło te 55ms?

Na podstawie podanej przeze mnie strony. Dokładna wartość pewnie nie istnieje, bo to jest właśnie cecha TTimer - brak dokładności.
Tak, zauważyłem - ale dalej nie wiem skąd oni to wzięli :)
Zobacz:
Interval TTimer TksTimer
----------------------------
100 108 100
50 62 50
20 31 20
10 15 11
5 15 6
2 15 3
1 14 2
Czyli mamy jakieś 13 ms...
A całość jest opisana w linku, który podałem wcześniej:
http://sergworks.wordpress.com/2010/04/06/a-better-tim...

Temat: Pytanie odnośnie tworzenia wątków

Diody sterowane są za pomocą protokołu DMX (komunikacja z diodą za pomocą konwertera podłączonego do USB)
Płynne zaświecenie diod polega na powolnym ich wygaszaniu i zapalaniu.
A oto pętle:

for Pos:=0 to 255 do
begin
sleep(10);
R:= Pos;
end;


for Pos:=0 to 255 do
begin
sleep(10);
R:= 255;
G:= Pos;
end;

for Pos:=0 to 255 do
begin
sleep(10);
R:= 255- Pos;
G:= 255;
end;

for Pos:=0 to 255 do
begin
sleep(10);
G:= 255;
B:= Pos;
end;

for Pos:=0 to 255 do
begin
sleep(10);
R:= Pos;
G:= 255- Pos;
B:= 255;
end;

for Pos:=0 to 255 do
begin
sleep(10);
R:= 255 - Pos;
B:= 255 ;
end;

for Pos:=0 to 255 do
begin
sleep(10);
B:= 255 - Pos;
end;

konto usunięte

Temat: Pytanie odnośnie tworzenia wątków

Daniel Wloochacz Grabowski:
Piotr L.:
Daniel Wloochacz Grabowski:
Skąd się wzięło te 55ms?

Na podstawie podanej przeze mnie strony. Dokładna wartość pewnie nie istnieje, bo to jest właśnie cecha TTimer - brak dokładności.
Tak, zauważyłem - ale dalej nie wiem skąd oni to wzięli :)
Zobacz:
Czyli mamy jakieś 13 ms...

Te 13 ms jest złudne.
TTimer simplifies the processing of the WM_TIMER messages
a z tego co wiem dostarczanie wiadomości w Windows nie jest deterministyczne - tak więc na dobrym sprzęcie opóźnienia mogą być nawet mniejsze, co nie znaczy że jak np. włączy się program pocztowy i zacznie coś ściągać to nagle opóźnienia nie zrobią się mega duże.

Dlatego podstawowy TTimer może powodować problemy - ale może do tego przypadku to wystarczy - zależy jak bardzo ważna jest stabilność.Piotr L. edytował(a) ten post dnia 19.04.12 o godzinie 21:35

konto usunięte

Temat: Pytanie odnośnie tworzenia wątków

Dariusz Sieńkowski:
Diody sterowane są za pomocą protokołu DMX (komunikacja z diodą za pomocą konwertera podłączonego do USB)
Płynne zaświecenie diod polega na powolnym ich wygaszaniu i zapalaniu.

No to najprościej jest użyć timera i kod umieścić w zdarzeniu OnTimer.


procedure TForm1.Timer1Timer(Sender: TObject);
begin
// instrukcje sterujące diodami
end;


Pytanie tylko czy standardowy TTimer będzie odpowiedni i jaki interwał ustawić? Oczywiście można również wykorzystać klasę TThread i tam umieścić kod tak jak to tutaj zostało już przedstawione a nawet można użyć kilku wątków pobocznych by sterować diodami niezależnie ale to już wedle uznania.
Daniel Grabowski

Daniel Grabowski Interaktywne
planowanie produkcji
on-line z MES

Temat: Pytanie odnośnie tworzenia wątków

Piotr L.:
Daniel Wloochacz Grabowski:
Piotr L.:
Daniel Wloochacz Grabowski:
Skąd się wzięło te 55ms?

Na podstawie podanej przeze mnie strony. Dokładna wartość pewnie nie istnieje, bo to jest właśnie cecha TTimer - brak dokładności.
Tak, zauważyłem - ale dalej nie wiem skąd oni to wzięli :)
Zobacz:
Czyli mamy jakieś 13 ms...

Te 13 ms jest złudne.
TTimer simplifies the processing of the WM_TIMER messages
a z tego co wiem dostarczanie wiadomości w Windows nie jest deterministyczne - tak więc na dobrym sprzęcie opóźnienia mogą być nawet mniejsze, co nie znaczy że jak np. włączy się program pocztowy i zacznie coś ściągać to nagle opóźnienia nie zrobią się mega duże.
Prawda, Windows nie jest systemem czasu rzeczywistego jest tzw. Soft RTOS - taki "identyczny z naturalnym" ;-)
Dlatego podstawowy TTimer może powodować problemy - ale może do tego przypadku to wystarczy - zależy jak bardzo ważna jest stabilność.
Chyba jednak nie wystarczy - jak zobaczyłem ten kod...
Daniel Grabowski

Daniel Grabowski Interaktywne
planowanie produkcji
on-line z MES

Temat: Pytanie odnośnie tworzenia wątków

Dariusz Sieńkowski:
Diody sterowane są za pomocą protokołu DMX (komunikacja z diodą za pomocą konwertera podłączonego do USB)
Acha, trzeba było tak od razu...
Masz tu przykładowy programik wraz z kodem źródłowym, który współpracuje z takim konwerterem:
http://www.meraprojekt.com.pl/files/USB2DMX512_V11_Del...
Kod jest prosty jak budowa cepa - sam zobaczysz, że to musi być wątek.
TTImer (i pochodne) się do tego po prostu nie nadaje....
Płynne zaświecenie diod polega na powolnym ich wygaszaniu i zapalaniu.
A oto pętle:
Dziwny ten kod jakiś... czemu tych pętli jest aż tyle a nie jedna?
Powinna być jedna, skoro ona iteruje zawsze w tym samym zakresie.

Temat: Pytanie odnośnie tworzenia wątków

Daniel Wloochacz Grabowski:
Dziwny ten kod jakiś... czemu tych pętli jest aż tyle a nie jedna?
Powinna być jedna, skoro ona iteruje zawsze w tym samym zakresie.

To dlatego, że to był mój pierwszy pomysł na rozwiązanie problemu.
A w związku z tym, że spełnia moje niewygórowane potrzeby to tak już zostawiłem :-)
Masz tu przykładowy programik wraz z kodem źródłowym, który współpracuje z takim
konwerterem:
http://www.meraprojekt.com.pl/files/USB2DMX512_V11_Del...

Dzięki za programik i kod źródłowy. Fajny tylko szkoda, że nie ma w nim zaprogramowanych żadnych czynności.
Będę próbował z tymi wątkami.
Dzięki wszystkim za zainteresowanie i pomoc
Pozdrawiam
Piotr M.

Piotr M. programista

Temat: Pytanie odnośnie tworzenia wątków

Dariusz Rorat:
Trochę niejasna sprawa dla mnie z tym bezpieczeństwem VCL. Z moich doświadczeń wynika, że najczęściej błędy w aplikacji były spowodowane błędami innych programistów, którzy stworzyli jakieś swoje komponenty.

I to jest właśnie problem. Większość programistów Delphi nie wie jak działa system (tutaj Windows) i co właściwie robi główny wątek aplikacji, ale nazywają się programistami i jeszcze biorą za to kasę. Jak się kiedyś zainteresujesz .NET-em czy choćby będziesz chciał napisać programik na Androida, to od razu dostaniesz po łapach przy pierwszej próbie dostępu do kontrolek z byle wątku. Czy można Cię winić za brak wiedzy w tym temacie? Niestety nie za bardzo, bo to Delphi jest takie badziewne, przynajmniej w tej kwestii ;]Peter M. edytował(a) ten post dnia 22.04.12 o godzinie 00:53

Następna dyskusja:

Pytanie techniczne




Wyślij zaproszenie do