Dynamiczne tworzenie równoległych wątków

2

Ja jak potrzebuję wątków to idę po prostu po najmniejszel lini oporu i robię to tak.
Najpierw odpalam wątek ,który robi za kierownika (uruchamia pracowników i czeka aż skończą pracę). Celowo używam najpierw wątka kierownika aby nie blokować głównego watku aplikacji.

type
  TSupervisorThread = class(TThread)
  private
    { Private declarations }
    CopiedProgress:integer;
  protected
    procedure Execute; override;
  end;

type
  TWorkerThread = class(TThread)
  private
    { Private declarations }
    ThreadIndex:integer;  
  protected
    procedure Execute; override;
  end;

var Progress:integer;

procedure TSupervisorThread.Execute;
var x:integer;
    WaitStatus,Threads:cardinal;
    WorkerThreadArray:array of TWorkerThread;
    WorkerThreadHandleArray:array of THandle;
begin

 Threads:=16; //np. 16 wątków 

  SetLength(WorkerThreadArray,Threads);
  SetLength(WorkerThreadHandleArray,Threads);
  
   for x:=0 to Threads-1 do
  begin
   
    WorkerThreadArray[x]:=TWorkerThread.Create(True);
    WorkerThreadHandleArray[x]:=WorkerThreadArray[x].Handle;
    WorkerThreadArray[x].FreeOnTerminate:=false;
    WorkerThreadArray[x].Priority:=tpNormal;
    WorkerThreadArray[x].ThreadIndex:=x;
    WorkerThreadArray[x].Resume;

  end;

  repeat
    WaitStatus:=WaitForMultipleObjects(Threads, @WorkerThreadHandleArray[0], True, 100);
    Synchronize(GetProgress);
    if Terminated=true then for x:=0 to Threads-1 do 
begin
    WorkerThreadArray[x].Terminate;
    if WorkerThreadArray[x].Suspended=true then WorkerThreadArray[x].Resume;
end;

  until WaitStatus<>WAIT_TIMEOUT;

  for x:=0 to Threads-1 do if Assigned(WorkerThreadArray[x])=true then FreeAndNil(WorkerThreadArray[x]);
  

end;

procedure TSupervisorThread.GetProgress;
begin
     CopiedProgress:=Progress; // albo pokazać gdzieś w GUI 
end;

procedure TWorkerThread.Execute;
begin
     {jakaś praca tutaj}
    Synchronize(UpdateProgress)
     
end;

procedure TWorkerThread.UpdateProgress;
begin
     Inc(Progress);
end;

0

Wygląda ciekawie!
A jak rozdzielić pracę na poszczególne wątki?

0

Najpierw trzeba przygotować listę rzeczy do zrobienia. Ja używam zwykłego TStringList.

Przed uruchomieniem wątków roboczych robisz

TaskList:=TStringList.Create; //TaskList jest zadeklorawana globalnie aby wszystkie wątki miały do niej dostęp podczas synchronizacji

TaskList.Add(FilePath) //ścieżka np. do jakiegoś pliku ,który trzeba przekonwertować w wątku

Dodajemy procedure CheckTaskList ,w której będziemy pobierać sobie coś do roboty. Lokalnie w wątku również deklarujemy sobie zmienną do której będziemy kopiować zadanie.

type
  TWorkerThread = class(TThread)
  private
    { Private declarations }
    ThreadIndex:integer;  
    Task:string;
    procedure CheckTaskList;
  protected
    procedure Execute; override;
  end;

Dalej chyba już powinno być już zrozumiałe,

procedure TWorkerThread.Execute;
begin

   repeat 

      Synchronize(CheckTaskList); 
      if Task<>'' then 
      begin
           {jakaś praca tutaj}
           Synchronize(UpdateProgress);
      end;

    until (Task='') or (Terminated=true);

end;
procedure TWorkerThread.CheckTaskList;
begin

    if TaskList.Count>0 then
    begin
         Task:=TaskList.Strings[0];
         TaskList.Delete(0);
    end
    else Task:='';

end;
2

W końcu udało się zaimplementować prosty system obsługi wątków, zgodnie z sugestiami z tego wątku (oraz innego, który traktował o klasach WMI)...
Jeśli ktoś chce zobaczyć efekty, proszę bardzo (patrz załącznik). Wątki śmigają i można zobaczyć co w danej chwili jest robione...
Pierwsze uruchomienie trwa nieco dłużej, ponieważ pobierane są wszystkie klasy WMI, później są odczytywane z cache...

Program jest oczywiście dopiero w fazie początkowej (jest częścią większego projektu). Ma za zadanie wyświetlić najważniejsze informacje o sprzęcie oraz systemie. Jego istotą NIE jest wyświetlenie szczegółowych informacji, tylko podstawowych, które pozwolą zwykłemu użytkownikowi zorientować się na czym de facto pracują i dlaczego ten sprzęt taki słaby :P

Jeśli ktoś ma jakieś uwagi, chętnie wysłucham. Mogą być błędy (z pewnością będą :)). Do zrobienia mam Ustawienia aplikacji, Tworzenie Raportu (txt, html) oraz system obsługi wersji językowych.

Ps: Jeśli AV zgłosi pretensje, nie przejmować się. Plik jest czysty (od dawna próbuję znaleźć skuteczną metodę, żeby programy AV nie zgłaszały nieistniejących zagrożeń w pliku generowanym przez Delphi... ale to walka z wiatrakami. Wydaje się, że jedyną skuteczną metodą jest zgłaszanie false-positive bezpośrednio producentowi). Być może wykupienie podpisu cyfrowego (ale to jest za drogie i nie ma gwarancji).

-Pawel

SysInfo.zip

1

Miodzio.Bardzo estetycznie wykonany program. Dobrze że używasz poprawnych jednostek binarnych (MiB,GiB...) zamiast MB,GB i traktowanie ich niepoprawnie jako MiB,GiB.
Taka pierdoła z mojej strony. Do wyświetlania np. użycia procesora nie używałbym standardowego ProgressBara bo to dziwnie wygląda. Użyłbym po prostu czegoś co nie generuje tej typowej animacji z "błyskiem".

Co do plucia się antywirków to znam to. Wystarczy że spakujesz .exeka np. głupim upx'em i Od razu jesteś traktowany jak "haksior"

0
Atak_Snajpera napisał(a):

Miodzio.Bardzo estetycznie wykonany program. Dobrze że używasz poprawnych jednostek binarnych (MiB,GiB...) zamiast MB,GB i traktowanie ich niepoprawnie jako MiB,GiB.

W wielu miejscach jednostki używane są poprawnie, ale co najwyżej nieintuicyjnie. Najważniejsze jest to, aby używać prawidłowych obliczeń względem wybranej skali — dzielenia np. przez 1000 w przypadku MB oraz przez 1024 w przypadku MiB.

Taka pierdoła z mojej strony. Do wyświetlania np. użycia procesora nie używałbym standardowego ProgressBara bo to dziwnie wygląda. Użyłbym po prostu czegoś co nie generuje tej typowej animacji z "błyskiem".

Już kiedyś pokazywałem użytkownikowi @Pepe jak zrobić wykres zużycia, taki sam jak ma Win10. Łatwe to i ładne. Ale to był tylko test — we właściwej kontrolce takiego wykresu użyłbym antialiasingu. ;)

Wystarczy że spakujesz .exeka np. głupim upx'em i Od razu jesteś traktowany jak "haksior"

No to nie pakuj, bo to żadnego sensu nie ma, a tylko zwiększasz prawdopodobieństwo wystąpienia problemów u użytkownika końcowego.

0

@Atak_Snajpera: Dzięki. UPX'a nie używam, właśnie z uwagi na fakt, że wtedy problemy są murowane... Rozmiar exe mi nie przeszkadza (i tak Delphi tworzy bardzo duże pliki wynikowe - ale w zamian dostaję wygodę i prostotę). A być może wydzielę obrazki (i inne zasoby) do osobnego pliku dll.

@furious programming: Użytkownik @Pepe pamięta bardzo dobrze i do dzisiaj jest wdzięczny za pomoc :) Jak już pisałem, jesteś dla mnie wzorem forumowicza - zawsze chętny od pomocy i zawsze przygotowany. Twoje posty są merytoryczne i pomocne.
Zaimplementuję kiedyś taką funkcjonalność (ale nie wiem czy w programie, bo w sumie ten akurat program jest dla mniej doświadczonych użytkowników... ale mam w planach stworzyć coś ala widżet na pulpit...

0

Dobre antivirki takie jak ten Microsoftowy automatycznie rozpakowują exeki przed analizą. Każdy inny ,który tego nie potrafi to przykład totalnej amatorki ze strony programisty i taki wyrób programopodobny nie jest warty instalowania. Ja używam upxa bo lubię jak binarki są małe. Taka stara szkoła...

1
Atak_Snajpera napisał(a):

Dobre antivirki takie jak ten Microsoftowy automatycznie rozpakowują exeki przed analizą. Każdy inny ,który tego nie potrafi to przykład totalnej amatorki ze strony programisty i taki wyrób programopodobny nie jest warty instalowania.

Tyle że to nadal nie zmienia faktu, że sam sobie tym rzucasz kłody pod nogi, nie mając żadnego sensownego powodu. Im więcej użytkowników, którym wyskoczą powiadomienia o zagrożeniach (nieistotne czy poprawnie czy nie), tym gorzej dla Ciebie i Twojego oprogramowania. Ja wiem, że nie każdy chce wydawać kasę na podpis cyfrowy i zadbać o każdy szczegół, aby system nie traktował programu z podejrzliwością.

Ja używam upxa bo lubię jak binarki są małe. Taka stara szkoła...

To nie jest sensowny powód — taka „stara szkoła” miała sens 20 lat temu, a od wielu lat rozmiar plików wykonywalnych nie ma większego znaczenia, bo przeciętnemu użytkownikowi ani nie brakuje miejsca na dysku i pamięci RAM, ani też nie cierpi z powodu zbyt wolnego łącza internetowego. Poza tym łącze to i tak nieistotny element, bo program jeśli już to pobiera raz i z głowy.

Dziś pakowanie jakichkolwiek plików za pomocą UPX-a i podobnych narzędzi praktycznie w ogóle nie ma sensu. Być może są specyficzne przypadki, aby było to uzasadnione, ale we wszelkich typowych zastosowaniach uzasadnienia nie ma. Tym bardziej, że takie bezcelowe pakowanie powoduje dodatkowe problemy, które łatwo jest uniknąć po prostu nie używając tego typu narzędzi. No chyba, że lubisz się tłumaczyć użytkownikom z tego, dlaczego antywirusy blokują Twój program, to spoko. ;)

0

Antivirki i bez tego się często plują ,więc jeden pies. Nieodpowiednia faza księżyca i jesteś "keyloggerem/mallware/spyware/bitcoin minerem...". Dobrze że chociaż co raz więcej ludzi rezygnuje z tych głupich zewnętrznych często problematycznych anitirków i korzysta z wbudowanego w windows. Ten przynajmniej nigdy nie ma problemów z moimi programikami (pakowanymi czy nie).

0

Heurystyka nie daleka od doskonałości i z tym niewiele można zrobić. Jednak jeśli ma się możliwość wykluczenia pewnej ilości fałszywych podejrzeń, to warto z niej skorzystać — tym bardziej, jeśli ta możliwość oznacza po prostu nie robienia niczego z plikiem wykonywalnym.

Natomiast niższy rozmiar pliku wykonywalnego można osiągnąć w sposób bezpieczny, po prostu usuwając z programu rzeczy niepotrzebne (np. nieużywane moduły z kodu źródłowego). Choć to i tak nie ma żadnego znaczenia, bo taka modułowa narośl nie waży więcej niż miegabajt. Tak więc wszelkie dodatkowe zabiegi mające na celu zmniejszenie rozmiaru pliku wykonywalnego po prostu nie mają żadnego sensu w dzisiejszych czasach.

0

Hey,
Jakiś czas temu pokazywałem jak program SysInfo działa (do gromadzenia informacji wykorzystuje WMI oraz wątki).

Od tego czasu udało mi się zaimplementować tworzenie raportu w formacie HTML (jeszcze chcę zrobić TXT). Dodałem również opcje (że można sobie poustawiać pod siebie). Aha, jeszcze dodam spis tresci (content/index) do raportu, żeby móc szybko przeskoczyć do interesującego nas działu).

W przyszłości jakieś wykresy i trochę info o programach (typu zainstalowane programy, działające procesy, etc).
Obciążenie procesora (ten pasek) zostanie zmieniony w przyszłości (prawdopodobnie na podział rdzenie/wątki).

Jak ktoś jest chętny, zapraszam do przetestowania. Jeśli macie jakieś sugestie, znajdziecie błąd - proszę o info.
Ps: Tłumaczenie nie jest zaimplementowane (program powinien być w języku angielskim, z wtrąceniami po polsku...

SysInfo.7z

1
Pepe napisał(a):

Hey,
Jakiś czas temu pokazywałem jak program SysInfo działa (do gromadzenia informacji wykorzystuje WMI oraz wątki).

Od tego czasu udało mi się zaimplementować tworzenie raportu w formacie HTML (jeszcze chcę zrobić TXT).

Zamiast tworzyć HTML, TXT czy inne XLSX wypluj te wszystkie dane do JSON.
Potem mozesz użyć szablonów mustache żeby zrobić z tego HTML, TXT czy co tam chcesz.
No i łatwo można to sobie potem dostosować do własnych czy innych potrzeb.
Mam na myśli to, że dane to dane - a ich wizualizacja, to wizualizacja i powinno to być całkowicie rozdzielone.

Poza tym, możesz to zapiąć w usługę, która będzie te dane zwracała real-time np. do Grafany ;-)

1 użytkowników online, w tym zalogowanych: 0, gości: 1