Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Delphi WaitForSingleObjectEx() ohne Timeout: Thread aufwecken (https://www.delphipraxis.net/107324-waitforsingleobjectex-ohne-timeout-thread-aufwecken.html)

EConvertError 25. Jan 2008 20:22


WaitForSingleObjectEx() ohne Timeout: Thread aufwecken
 
Hallo!

Ich benutze folgenden Code in einem Thread:
Delphi-Quellcode:
dwWait := WaitForSingleObjectEx(
      FConnectEventHandle, // event object to wait for
      INFINITE,            // we have plenty of time
      true);
Eigentlich bin ich sehr zufrieden damit, da es sehr ressourcensparend ist und ich eigentlich keine Timeouts brauche.

Allerdings gibt es ein paar Fälle, wo ich den Thread beenden muss (z.B. Programmende). Da der Thread geblockt ist, kann ich Terminated nicht regelmäßig prüfen.

Multithreading the Delphi Way (das beste Schriftstück, für Threads IMHO :mrgreen:) sagt dazu:
Zitat:

If your thread blocks, as a result of any of the synchronization mechanisms discussed later, you may have to override the terminate method to unblock your thread.
Nur habe ich keine Ahnung, wie man das macht:
1) Wie killt man so ein WaitForSingeObjectEx?
2) Wird Terminate() überhaupt ausgeführt, wenn der Thread geblockt ist? Ich nehme schon sehr stark an, aber...

Danke,
Andreas

sirius 25. Jan 2008 20:32

Re: WaitForSingleObjectEx() ohne Timeout: Thread aufwecken
 
Ja klar, wird die Methode ausgeführt. sie läuft ja im MainThread. Und du löst in der überschriebenen Methode dann dein Ereignis aus.

EConvertError 25. Jan 2008 20:44

Re: WaitForSingleObjectEx() ohne Timeout: Thread aufwecken
 
Verstehe. Also überschreibe ich einfach die Terminate()-Methode meines Threads.

Also kann ich einfach mein Ereignis mit SetEvent() auslösen? Was mich bei dieser Geschichte am brennendsten interessiert: Welchen Rückgabewert hat dann WaitForSingleObjectEx? 0 und WAIT_IO_COMPLETION sind nämlich OK, alles andere wird als Fehler gerechnet. Jetzt wäre es gut, wenn ich es als Fehler rechnen könnte...

Danke,
Andreas

alzaimar 25. Jan 2008 20:53

Re: WaitForSingleObjectEx() ohne Timeout: Thread aufwecken
 
Ich setze einfach Terminated auf TRUE und zupfe dann am Event: Der Thread wacht auf und merkt 'Shit, muss mich beenden' und hört auf.

EConvertError 25. Jan 2008 20:59

Re: WaitForSingleObjectEx() ohne Timeout: Thread aufwecken
 
Soweit habe ich das verstanden, nur:

Wie "zupfe" ich am Event (normalerweise wird das in diesem Fall von Windows erledigt)? Ich tippe auf SetEvent(FConnectEventHandle).

Und ihr meint, dass mir der Rückgabewert von WaitForSingleObjectEx egal sein kann, weil ich einfach Terminated prüfe? Würde zumindest für mich logisch klingen...

Danke,
Andreas

alzaimar 25. Jan 2008 21:48

Re: WaitForSingleObjectEx() ohne Timeout: Thread aufwecken
 
Ja genau, Du löst das Event aus. Es ist nicht 100% genau, weil theoretisch der Event in dem Augenblick ausgelöst wird, in dem Du den Thread terminieren willst. In deinem Fall (Thread zum Prozessende terminieren) ist das aber wurscht.

Christian Seehase 25. Jan 2008 21:59

Re: WaitForSingleObjectEx() ohne Timeout: Thread aufwecken
 
Moin Andreas,

je nachdem, was der Thread tun soll, wenn das Event eintritt, könntest Du dann auch noch, zur Sicherheit, ein Flag setzen, anhand dessen der Thread erkennt, dass er abgebrochen wurde.
Dadurch kannst Du verhindern, dass eventuell noch weitere Aktionen eines normalen Durchlaufes ausgeführt werden.

negaH 26. Jan 2008 07:55

Re: WaitForSingleObjectEx() ohne Timeout: Thread aufwecken
 
inetwa so baue ich meine Threads auf:

Delphi-Quellcode:
type
  TMyThread = class(TThread)
  private
    FEvents: array[0..1] of THandle;
    function GetEvent(Index: Integer): THandle; // Result := FEvent[Index];
  protected
    procedure Execute; override;
  public
    constructor Create(..params);
    destructor Destroy; override;

    property EventTerminate: THandle index 0 read GetEvent;
    property EventWorking: THandle index 1 read GetEvent;
  end;

procedure TMyThread.Execute;
begin
  try
    while not Terminated do
      case WaitForMultipleObjects(@FEvents, 2, .....) of
        WAIT_OBJECT_0 +0:
          Break;
        WAIT_OBJECT_0 +1:
          // ... mache sonstwas;
      else
        raise Exception.Create('ungültiges Resultat in Wait');  
      end;
  except
//    ...alle Exceptions hier behandeln
  end;
end;
Falls ich mehrere Events benötige dann baue ich FEvents[] als privates Feld der TThread Klasse und greife per indizierten Properties auf dieses Array zu. Das ist im Grunde der häufigste Fall der zutrift da man am besten mit Threads und Eventorientierten Funktionen arbeiten sollte, zb. Kommunikation per COM/Bluetooth/WinSock usw.

Gruß Hagen

EConvertError 26. Jan 2008 17:02

Re: WaitForSingleObjectEx() ohne Timeout: Thread aufwecken
 
Verstehe.

D.h. die simple Methode, die für mich eventuell ausreicht, ist: Ich löse das Event aus und setze die Terminated-Property?

Die Königslösung (und die strebe ich an) ist für das Beenden ein eigenes Event zu registrieren und statt WaitForSingeObjectEx mit WaitForMultipleObjects zu arbeiten.

Werde das gleich mal einbauen und mich bei weiteren Problemen melden...

Vielen Dank,
Andreas

negaH 27. Jan 2008 12:35

Re: WaitForSingleObjectEx() ohne Timeout: Thread aufwecken
 
Ja, für jeden Zustand ein eigenes Event, oder aber ein threadsicheres Flag/Set und bei Änderung dieses, ein Event auslösen. Ich bevorzuge das Erstere da man dadurch mehrere dieser Events asynchron auslösen kann bzw. wenn man Eventbasierte APIs benutzt auch strikt nach Funktion separieren kann ohne Seiteneffekte zu provozieren. Das WaitForMultipleObjects() lässte sich auch einfach ersetzen durch MsgWaitForMultipleObjects() um einen Messagequeue zum Thread zu berücksichtigen.

Gruß hagen


Alle Zeitangaben in WEZ +1. Es ist jetzt 19:17 Uhr.
Seite 1 von 2  1 2      

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