Wątki - nie potrafię ich obsługiwać.

0

Witam.
Czytałem nieco o wątkach, jednak nie potrafię ich używać na tyle dobrze jak tego chcę.
Umiem zrobić np, by do spinedit dodawane było cały czas 1 do osiągnięcia np. 9999999 itp, jednak potrzebuję czegoś innego xd
Gdy próbowałem to zobić samemu to niestety, ale nie dałem rady.
W moim programie mam kilka funkcji przypisanych do timerów. Jednak wolałbym to zamienić na wątki (są dokładniejsze i nie zacinają tak programów).
Chciałbym na początek ogarnąć funkcję np. playsound.
W timerze wygląda to tak:

 begin
if edit2.Text = ('Alarm') then
SNDPlaySound('Alarm.wav', SND_FILENAME OR SND_ASYNC);
end;

Jak to jednak przełożyć na wątek?

0

musisz to włożyć w metodę wątku pt. "synchronize"

0

Ale po co Ci do tego wątek przecież funkcja SNDPlaySound wcale nie musi być w wątku aby nie blokowała programu do tego właśnie służy flaga SND_ASYNC.

0
begin
edit1.text := CheckingTAB(TabID);
if edit1.text = ('TAB') then edit2.Text := ('TAB Pressed');
end;

Coś takiego też mam w timerze (dodam Od razu że chodzi o grę, żeby jakiś Sherlock nie pisał aaa tu chodzi o grę, wiec nie pomogę). CheckingTAB jest podobne to funkcji czytania string z pamięci.
Da radę coś takiego również przełożyć na wątek?

0

Reakcję na klawisze się robi w standardowej procedurze obsługi komunikatów w Delphi od tego masz zdarzenia OnKey... nadal nie widzę potrzeby zaprzęgania do tego wątku. Napisz konkretnie ewentualnie podaj kod to podpowiemy jak to rozwiązać.

0

Nie sądzę by onkey było tym o co mi chodzi i czego potrzebuję. Wolałbym to przypisać do wątku. Jakis pomysł jak to zrobić?

0

No niby mozesz zamiast timera odpalic watek. Mozesz to zrobic tak:


type
  TWatek = class(TThread)
  private
    procedure GrajDzwiek;
  protected
    procedure Execute; override;
  end;

procedure TWatek.GrajDzwiek;
begin
    if Form1.edit2.Text = ('Alarm') then
    SNDPlaySound('Alarm.wav', SND_FILENAME OR SND_ASYNC);
end;


procedure TWatek.Execute;
var
stop:boolean;
begin
stop:=false;

  repeat

    Synchronize(@GrajDzwiek);

  Sleep(1000);
  until stop=true;

end;

No i masz watek, ktory lata sobie w nieskonczonej petli co sekunde i sprawdza pole.

Mozesz go odpalic w ten sposob:

TWatek.Create(false);

Tylko odczytywanie pola Edit jest slabe i musialbys to rozwiazac jakos inaczej ;)

1

W zdarzeniu "onkey.." podpiętym pod Edita sprawdzasz treść edita i odpowiednio ustawiasz flagę, "grać" albo "nie grać" ....
Sam wątek sprawdza tylko flagę i na podstawie jej wartości odpala melodyjkę.
Jeśli flaga będzie typem prostym np. byte albo boolean (co w sumie na jedno wychodzi) to jej ustawienie przez "onkey.. ", oraz sprawdzenie przez wątek, nie wymagało by nawet specjalnych mechanizmów takich jak synchronize, sekcje krytyczne ,mutexy czy semafory , których odpowiednie zastosowanie umożliwia zapewnienie chwilowego wyłącznego dostępu do wspólnych zasobów przez wątek. Bo ta wyłączność powinna być zapewniona sprzętowo, na poziomie wielowątkowego dostępu do pamięci procesu. Jeśli się mylę to proszę o sprostowanie .

0

Dzięki.
Chodzi o to że funkcja readingtab sprawdza pewien adres... gdy w tym adresie pojawi się TAB to wtedy coś tam się dzieje. Zależy mi na wymianie timera na coś bardziej dokładnego, gdyż nawet timer na interval 1 nie wyłapuje czasem wartości z TAB. Postaram się coś poczytać o tym OnKey niedługo.

0

"Zależy mi na wymianie timera na coś bardziej dokładnego"
"coś bardziej dokładnego ", co masz na myśli , chcesz mierzyć czas timerem ?

0

Wartość z adresu zmienia się bardzo często i zostaje ona zapisywana do edit.text. Może to być kropka, albo inne coś... Interval ustawiony na 1ms czasami nie wyłapuje wszystkiego i z tego właśnie względu muszę ogarnąć coś innego.

0

podaj kod ....

0

To jest niewypał z czegoś co miało być wątkiem:

type
TTest = class(TThread)
protected
procedure Execute; override;
end;


const
TabID = $4D12DF;




implementation

function CheckingTAB(Address: Integer): String;             //do TAB... czyta tylko 3 znaki.
var
NB : LongWord;
Temp : ARRAY [1..255] OF Byte;
I : Byte;
IDProcess, proc_ID : Cardinal;
begin
GetWindowThreadProcessID(FindWindow('GameClient', nil), @proc_ID);
IDProcess := OpenProcess(PROCESS_ALL_ACCESS, false, proc_ID);
Result := '';
ReadProcessMemory(IDProcess, Ptr(Address), @Temp[1], 255, NB);
for I := 1 to 3 do
begin
if ((Temp[I] = 0) or (Temp[I] = $0F)) then
Break;
Result := Result + Chr(Temp[I]);
end;
end;




procedure TTest.Execute;
begin
repeat
form1.edit1.text := checkingtab(tabcid);
until form1.edit1.text := 'TAB;
end;
end. 

Konkretnie tu:

 procedure TTest.Execute;
begin
repeat
form1.edit1.text := checkingtab(tabcid);
until form1.edit1.text := 'TAB';
end;
end.

pojawia się problem że musi to być boolean.

0

opisz sensownie problem , sformatuj kod tak aby był czytelny, może wtedy ktoś Ci pomoże

0

A co jest nieczytelne w tym kodzie?

Wątek (jakby działał) miałby mieć za zadanie czytanie zawartości z adresu z clienta gry i zapisywanie go w edit.text.
Nic więcej, nic mniej xd

0
until form1.edit1.text := 'TAB';

Co to jest? I dziwisz się wielce błędowi, że "musi to być boolean".

0

Może faktycznie.
Spróbowałem inaczej:

 procedure TTest.Execute;
var
quit : string;
begin
quit := Form1.Combobox1.Text;

While quit = 'Start' do
begin
repeat
form1.edit1.text := checkingtab(tabid);
until quit = 'Stop';
form1.edit1.Text := 'stopped';
end;
end;

Sprawdza cały czas ten adres i zapisuje jego value do edit1, także elegancko.. jednak gdy zmienię w comboboxie.text na Stop to się nie zatrzymuje xd

0

Udało mi się to zrobić, jednak nadal w tym adresie pojawia się tak dużo info że jednak czasem nie wykrywa wciśniętego TAB xd

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