Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Delay(sleep) nicht synchron,gegenseitige Blockade (https://www.delphipraxis.net/114124-delay-sleep-nicht-synchron-gegenseitige-blockade.html)

stoxx 20. Mai 2008 05:22


Delay(sleep) nicht synchron,gegenseitige Blockade
 
wenn man dieses Delay Funktion von Hagen verwendet, geht die Synchronität verloren, gibts denn da eine Möglichkeit, das trotzdem zu realisieren?

http://www.delphipraxis.net/internal...elay+revisited


wenn man Button1 drückt, und gleich darauf Button2 ... dann kehrt Button1 erst zurück, NACHDEM Button2 fertig ist, obwohl in Button1 nur 1000 msec Verzögerung angegeben ist, gegenüber 10 Sekunden bei Button2 ....




Delphi-Quellcode:
procedure Delay(Milliseconds: Integer);
var
  Tick: DWord;
  Event: THandle;
begin
  Event := CreateEvent(nil, False, False, nil);
  try
    Tick := GetTickCount + DWord(Milliseconds);
    while (Milliseconds > 0) and
          (MsgWaitForMultipleObjects(1, Event, False, Milliseconds, QS_ALLINPUT) <> WAIT_TIMEOUT) do
    begin
      Application.ProcessMessages;
      if Application.Terminated then Exit;
      Milliseconds := Tick - GetTickcount;
    end;
  finally
    CloseHandle(Event);
  end;
end;


//==============================================================================

procedure TForm2.Button1Click(Sender: TObject);
begin
   sleepX(1000);
   ShowMessage('Button1');
end;
//==============================================================================


procedure TForm2.Button2Click(Sender: TObject);
begin
   sleepX(10000);
   ShowMessage('Button2');
end;

//==============================================================================

new32 20. Mai 2008 16:33

Re: Delay(sleep) nicht synchron,gegenseitige Blockade
 
Du kannst das Problem mit 2 separaten Threads lösen:

Delphi-Quellcode:
function m1(arg:pointer):DWORD;stdcall;
begin
 sleep(2000);
 MessageBox(form1.Handle,'','',MB_OK);
 result:=0;
end;

function m2(arg:pointer):DWORD;stdcall;
begin
 sleep(5000);
 MessageBox(form1.Handle,'','',MB_OK);
 result:=0;
end;

procedure TForm1.Button1Click(Sender: TObject);
id:cardinal;
begin
CreateThread(nil, 0, @m1, nil, 0, id);
end;

procedure TForm1.Button2Click(Sender: TObject);
id:cardinal;
begin
CreateThread(nil, 0, @m2, nil, 0, id);
end;

shmia 20. Mai 2008 16:47

Re: Delay(sleep) nicht synchron,gegenseitige Blockade
 
Stell dir folgende Geschichte vor:
Zitat:

Dein Chef A sagt dir, du solltst eine Akte holen.
Auf dem Weg kommt die Chef B in die Quere und verlangt du sollst ihm einem Kaffe kochen.
Du machst also zuerst den Kaffee und bringst dann die Akte.
Dann gibt's Mecker von Chef A, weil du so spät dran bist.
Hättest du Chef B gesagt, dass du gerade keine Zeit hast, hätte es das Problem nicht gegeben.

In deinem Beispiel tritt ein vergleichbares Problem auf:
durch Aufruf von Application.ProccessMessages werden Mausklicks und Tastatureingaben sofort bearbeitet und die aktuelle Funktion (Delay()) solange unterbrochen.

In einer richtigen Anwendung würde man einfach die meisten Buttons (oder besser Actions) ausschalten (.Enabled := False) bis der Vorgang angeschlossen ist.
Das wäre die sauberste Lösung denn der Benutzer sieht schon optisch, dass die Anwendung beschäftigt ist und keine neuen Befehle annehmen kann.

Andere Möglichkeit: Innerhalb von Delay() statt Application.ProcessMessages nur die notwendigen Paint-Messages verarbeiten.

stoxx 20. Mai 2008 17:26

Re: Delay(sleep) nicht synchron,gegenseitige Blockade
 
@new32 .. Thread wäre komplett falsch, es geht um Warte und Synchronisationsprobleme, es geht quasi darum, dass die Button1Click Procedure wirklich mit der Ausführung wartet. (auf gewisse Zustände des programmes / Flags) nur im Hauptthread. Eventuell sogar mit Threads dazu, da läuft was noch nicht rund.

Anwendung der Delay funktion wäre dann folgende:

Delphi-Quellcode:
While not Flag do
  Delay(50);


@shmia ... die Button Anwendung ist nur ein Beispiel ... ich hab aber schon ungefähr eine grobe Vorstellung, wie es gehen müsste. Die schleife für app.processmessages dürfte nur einmal laufen, und müsste ein Array aller procedure Eintritte prüfen, damit sowas parallel laufen kann ..
ist mir aber noch nicht ganz klar, wie das gehen soll, und ob das wirklich funktioniert

stoxx 20. Mai 2008 17:57

Re: Delay(sleep) nicht synchron,gegenseitige Blockade
 
ich glaube, das geht wirklich nicht .. Mißt .. :(
Da ja Button1 dann eigentlich im Aufrufstack hängt und unterbrochen wird. und somit die Button2click eigentlich in der Button1click procedure ausgeführt wird und Button1click keine Chance hat, eher zurückzukehren, als Button2click ...

blöd .. aber ist halt eben nur ein Thread :)

shmia 20. Mai 2008 18:05

Re: Delay(sleep) nicht synchron,gegenseitige Blockade
 
Erzähl mal was dein Programm eigentlich tun soll.

Es gibt ja noch andere Möglichkeiten wie z.B. eine Liste mit Elementen.
Jedes Element enthält einen Zeitpunkt und einen "Aktionscode".
Wenn man neue Elemente in die Liste einfügt wird diese gleich wieder nach aufsteigenden Zeitpunkten sortiert.
Ein Dispatcher-Funktion sorgt dann dafür, dass wenn die kleinste Zeit erreicht wird, das Element aus der Liste genommen und die Aktion ausgeführt wird.

Olli73 20. Mai 2008 18:22

Re: Delay(sleep) nicht synchron,gegenseitige Blockade
 
Zitat:

Da ja Button1 dann eigentlich im Aufrufstack hängt und unterbrochen wird. und somit die Button2click eigentlich in der Button1click procedure ausgeführt wird und Button1click keine Chance hat, eher zurückzukehren, als Button2click ...
Ja genau; Button1Click macht erst weiter wenn Button2Click fertig ist.

Die Lösung kann eigentlich nur sein, alles was nach dem Delay kommt in eine eigene Procedure auszulagern und anstatt dem Delay einen Timer (oder etwas ähnliches) zu aktivieren, der dann die "ausgelagerte" Procedure aufruft.

Gruß
Olli

stoxx 20. Mai 2008 19:04

Re: Delay(sleep) nicht synchron,gegenseitige Blockade
 
Zitat:

Erzähl mal was dein Programm eigentlich tun soll.

es geht wahrscheinlich dann nur über eine "ausgelagerte" Procedure, wie Olli vorgeschlagen hat.
Die Idee mit dem Aktionscode ist interessant, wobei ich mir noch überlege, ob das für mein Problem relevant ist. Aber merken werde ich es mir auf alle Fälle..
Ich hatte eigentlich ein anderes Problem, wo das Delay in Zusammenarbeit mit Threads nicht funktioniert, ich dachte fälschhlicherweise, wenn ich erstmal das heruntergebrochene Delay-Problem gelöst habe, kann ich mein ursrpüngliches Problem lösen.. eigentlich war das gar nicht das Hauptproblem ..



Es trat das Probelem auf, dass im Delay Aufruf auf ein Flag gewartet wird, welches auf einen zweiten Thread wartet ... bzw. der zweite Thread setzt das Flag ... nicht direkt, sondern per Synchronize. Aber komischwerweise wartet der Thread nun auch, bis delay fertig ist, und hat nicht die Möglichkeit das Flag zwischendurch zu setzen, schon komisch ... Der Synchronize aufruf geht eben wahrscheinlich nicht über die Nachrichtenwarteschleife des PRogramms ...

Der Vorschlag von Olli ist dann wahrscheinlich das, was ich brauche.
Oder eventuell umständliche Joblisten mit Objekt zwischenkopien.
Im Moment noch etwas ratlos bin ..

sirius 21. Mai 2008 08:17

Re: Delay(sleep) nicht synchron,gegenseitige Blockade
 
Bitte auch immer Beitrag 17 hier lesen.
Wie shmia schon sagte, muss dein PRoblem auch anders zu lösen sein. Daz müssen wir aber erstmal das Problem kennen.


Alle Zeitangaben in WEZ +1. Es ist jetzt 20:05 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz