Wątek mi nie działa

0

Witam.

Piszę temat, gdyż nie mogę Sobie poradzić z wątkiem.
Jego kod wygląda tak:

Kopiuj
unit Unit9;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, Tlhelp32, StdCtrls, PsAPI, Vcl.Samples.Spin, Vcl.ExtCtrls, Math,
  Vcl.Menus, MMSystem;

type
  TAlarm = class(TThread)
  private

  protected
    procedure Execute; override;
  end;

 var
  Alarm:TAlarm;


implementation
uses Unit1;



procedure TAlarm.Execute;
begin
  FreeOnTerminate := true;
  while not self.terminated do
begin
if (Form1.Label7.Caption >= '100') then
begin
SNDPlaySound('Danger.wav', SND_FILENAME OR SND_ASYNC);
end;
end;
end;



Initialization
Alarm := TAlarm.Create(True);

end.

Chcę, by wątek sprawdzał mi label7 i jeżeli liczba w nim zapisana jest większa od 100 to żeby wył tak zwany alarm.

Checkbox wygląda tak:

Kopiuj
procedure TForm1.CheckBox7Click(Sender: TObject);
begin
  if Checkbox7.Checked then
  begin
    Alarm.Resume;
  end
  Else
  begin
    Alarm.Suspend;
  end;
end;

Nie chcę tego robić w timerze, co by było łatwiejsze.
Proszę o pomoc.
Dziękuję

edytowany 1x, ostatnio: aurel
abrakadaber
abrakadaber
  • Rejestracja:ponad 12 lat
  • Ostatnio:7 miesięcy
  • Postów:6610
1

-1. CO TO ZNACZY NIE DZIAŁA?
0. formatuj kod

  1. użyj debuggera
  2. jeśli ma sprawdzać czy to co jest w label jest większe od 100 to musisz to zamienić na liczbę i z liczbą porównywać bo napis 2 jest większy od napisu 100
  3. dodaj po każdym sprawdzeniu sleep(100) - teraz sprawdzasz cały czas w kółko i o ile UI się nie wiesza to zużycie procesora na jednym rdzeniu masz 100%
  4. SND_ASYNC + wątek + brak sleep sprawi, że dźwięk będzie uruchamiany cały czas od nowa bez czekania aż poprzedni się skończy
  5. o ile tu nie jest to jakiś błąd (szczęście początkującego) to odwoływanie się z wątku do elementów UI jest niepoprawne
  6. masz ogromne braki w podstawach a bierzesz się za jedną z najtrudniejszych rzeczy - programowanie wielowątkowe. Chyba chcesz za dużo przeskoczyć

Chcesz pomocy - pokaż kod - abrakadabra źle działa z techniką.
edytowany 1x, ostatnio: abrakadaber
flowCRANE
Moderator Delphi/Pascal
  • Rejestracja:ponad 13 lat
  • Ostatnio:około 5 godzin
  • Lokalizacja:Tuchów
  • Postów:12164
0

W sumie to jeśli dźwięk z pliku Danger.wav jest długi np. na kilka sekund to obecny kod może zostać - wystarczy usunąć flagę SND_ASYNC. W ten sposób program będzie oczekiwał na zakończenie odgrywania dźwięku, a że całość działa w wątku pobocznym, to interfejsu nie zamrozi, a i zużycie procka spadnie.

Co do reszty - poprzednik podał wystarczająco dużo niedociągnięć.


Pracuję nad własną, arcade'ową, docelowo komercyjną grą z gatunku action/adventure w stylu retro (pixel art), programując silnik i powłokę gry od zupełnych podstaw, przy użyciu Free Pascala i SDL3. Więcej informacji znajdziesz na moim mikroblogu.
edytowany 1x, ostatnio: flowCRANE
P2
  • Rejestracja:około 10 lat
  • Ostatnio:prawie 5 lat
  • Lokalizacja:okolice Pińczowa
  • Postów:73
0
Kopiuj
(Form1.Label7.Caption >= '100')

Przecież do komponentu Label nie wprowadzasz.
Utwórz dodatkową zmienną, aby z niej korzystał wątek (może być w klasie, lub globalna), gdyż korzystanie z kontrolek jest wolne, a i bez synchronize() (co było wspomniane) powoduje błędy.
Poza tym, tak jak napisali w poprzednich - porównywać trzeba liczby, a nie łańcuchu tekstowe.
Zmienna pomocnicza powinna być typu liczbowego i być aktualizowana wraz z Label7 (konwersja typów).

I ogólnie nie widzę potrzeby kilku wątków.
W końcu wraz z modyfikacją Label7 (robisz to z kodu) możesz uruchomić dźwięk (z SND_ASYNC z głównego wątku) i ewentualnie go zatrzymać za pomocą SND_PURGE.

JU
  • Rejestracja:około 22 lata
  • Ostatnio:około miesiąc
  • Postów:5042
0

Korzystanie z kontrolek jest wolne? No bez przesady. Fakt, szybciej odczytać zwykłą zmienną niż właściwość kontrolki, ale to w takim przypadku nie jest w ogóle zauważalne.

Poza tym jeśli chodzi o Synchronize, to jest potrzebne przy ZAPISIE. Przy odczycie nie ma żadnego sensu. Jednak nie jest ładnie tak mieszać logikę z GUI i powinieneś tutaj zadbać o to, żeby nie odczytywać bezpośrednio danych z kontrolki, tylko w jakiś inny sposób. Ale staraj się nie używać zmiennych globalnych, bo to też nie jest dobre. Pole do popisu masz spore. Ja w pierwszym strzale zrobiłbym callbacka, który by mi zwracał odpowiednią wartość.

edytowany 1x, ostatnio: Juhas
flowCRANE
Moderator Delphi/Pascal
  • Rejestracja:ponad 13 lat
  • Ostatnio:około 5 godzin
  • Lokalizacja:Tuchów
  • Postów:12164
0

@Juhas:
Fakt, szybciej odczytać zwykłą zmienną niż właściwość kontrolki [...]

Wszystko zależy od tego jak to wygląda pod spodem - czy właściwość daje bezpośredni dostęp do pola, czy jednak posiada akcesor z jakąś logiką. Być może dostęp bezpośredni do pola może być na niskim poziomie redukowany do operacji atomowej, ale tego nie jestem pewien.

Poza tym jeśli chodzi o Synchronize, to nie jest potrzebne przy ZAPISIE.

Obstawiam, że przez przypadek napisałeś to "nie". Jeśli zapis jest atomowy (np. modyfikacja inta) to nic nie trzeba synchronizować. Jednak jeśli modyfikuje się dane o większej wadze to jest konieczna - tym bardziej, jeśli co najmniej dwa wątki mają możliwość ingerencji w te dane.

Przy odczycie nie ma żadnego sensu.

Owszem - ma sens. Wyobraź sobie co się stanie, jeśli jeden wątek będzie modyfikował bufor danych o wadze kilku megabajtów, a drugi wątek w tym czasie będzie z tego bufora odczytywał. O ile nie skończy się to wyjątkiem, to wątek czytający z bufora może odczytać dane częściowo zmodyfikowane.


Pracuję nad własną, arcade'ową, docelowo komercyjną grą z gatunku action/adventure w stylu retro (pixel art), programując silnik i powłokę gry od zupełnych podstaw, przy użyciu Free Pascala i SDL3. Więcej informacji znajdziesz na moim mikroblogu.
edytowany 2x, ostatnio: flowCRANE
JU
  • Rejestracja:około 22 lata
  • Ostatnio:około miesiąc
  • Postów:5042
0

Jakoś to "nie" wkradło mi się przypadkiem, nie wiem skąd. Natomiast tutaj piszemy o pobieraniu danych z okienka GUI. W przypadku pytacza, to nie są RichEdity z milionami znaków, tylko proste labele, więc tutaj odczyt z Synchronize nie ma sensu. Natomiast zgodzę się z tym, co mówisz, czyli przy dużych paczkach danych ma to sens. Chociaż tutaj też się rodzi pytanie, jak to działa pod spodem. Czy update takiej paczki jest operacją atomową, czy nie. No, jeśli zmieniamy zawartość w pętli, no to sprawa jest jasna. Ale jeśli robimy to jedną operacją, to już niekoniecznie jednak :)

0

Dziwne, mi działa.

flowCRANE
Moderator Delphi/Pascal
  • Rejestracja:ponad 13 lat
  • Ostatnio:około 5 godzin
  • Lokalizacja:Tuchów
  • Postów:12164
0
Juhas:

W przypadku pytacza, to nie są RichEdity z milionami znaków, tylko proste labele, więc tutaj odczyt z Synchronize nie ma sensu.

Owszem, jednak Ty napisałeś o synchronizacji ogólnie, bez rozróżnienia przypadków, co może wprowadzać w błąd - stąd mój komentarz.

Natomiast zgodzę się z tym, co mówisz, czyli przy dużych paczkach danych ma to sens.

Tu nie chodzi o rozmiar danych, a o skalę modyfikacji. Im dłużej trwa owa modyfikacja i ma większą złożoność, tym większe prawdopodobieństwo, że inny wątek wtrąci się w nieodpowiednim momencie i albo spowoduje tym powstanie wyjątku, albo odczyta na wpół zmodyfikowane dane. W obu przypadkach jest to katastrofa.

Ale jeśli robimy to jedną operacją, to już niekoniecznie jednak :)

Jeśli owa operacja jest atomowa to nie trzeba, bez względu na to czy dotyczy odczytu czy modyfikacji :]


Pracuję nad własną, arcade'ową, docelowo komercyjną grą z gatunku action/adventure w stylu retro (pixel art), programując silnik i powłokę gry od zupełnych podstaw, przy użyciu Free Pascala i SDL3. Więcej informacji znajdziesz na moim mikroblogu.
edytowany 1x, ostatnio: flowCRANE
Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)