Delphi-PRAXiS
Seite 2 von 4     12 34      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi W1000 Symbol 'Resume' ist veraltet ???? (https://www.delphipraxis.net/149714-w1000-symbol-resume-ist-veraltet.html)

EWeiss 22. Aug 2011 22:38

AW: W1000 Symbol 'Resume' ist veraltet ????
 
Zitat:

Zitat von Tryer (Beitrag 1118743)
Das Suspend würde ich nicht durch Terminate ersetzen, das funzt halt einfach nicht.

Das "gefähliche" Suspend von aussen würde ich halt vermeiden indem ich nur ein Flag setze über welches der Thread sich zu einem sicheren Zeitpunkt (wenn er gerade nichts blockiert) selber unterbricht. Das Fortsetzen (ResumeThread) ist dann unkritisch.

Grüsse, Dirk

Ist schon seltsam das man sich selbst noch funktionen basteln muss, darauf hingewiesen wird das Resume veraltet ist
aber keine Anwendbare lösung dafür zur verfügung stellt.

Werd wohl nicht drum rum kommen da selbst was zu basteln.

Danke.

gruss

jaenicke 23. Aug 2011 05:04

AW: W1000 Symbol 'Resume' ist veraltet ????
 
Naja, die ganze Konstruktion mit Suspend und Resume war eben potentiell gefährlich.

Deshalb ist es besser da etwas individuell auf den konkreten Fall angepasst zu schreiben als etwas einfaches zu nutzen, das zu schwer zu findenden massiven Problemen (wie schon genannt Deadlocks) führen kann.

Zumal man den Ablauf dabei auch gleich viel besser optimieren kann.

himitsu 23. Aug 2011 05:46

AW: W1000 Symbol 'Resume' ist veraltet ????
 
Zitat:

Zitat von EWeiss (Beitrag 1118744)
... darauf hingewiesen wird das Resume veraltet ist
aber keine Anwendbare lösung dafür zur verfügung stellt.

Das würde ich so nicht ganz behaupten.

Delphi-Quellcode:
    // This function is not intended to be used for thread synchronization.
    procedure Resume; deprecated;
    // Use Start after creating a suspended thread.
    procedure Start;
    // This function is not intended to be used for thread synchronization.
    procedure Suspend; deprecated;
Wobei die D2010-OH diesbezüglich wirklich schrottig ist,
denn bei Delphi-Referenz durchsuchenTThread.Suspend und Delphi-Referenz durchsuchenTThread.Resume wird nicht erwähnt, daß diese "alt" sind,
aber bei Delphi-Referenz durchsuchenTThread.Start steht wenigstens
Zitat:

Anmerkung: Die Methode Resume ist veraltet und seine Verwendung soll vermieden werden. Verwenden Sie stattdessen die Methode Start.
Nur wie soll man das eigentlich entdecken, wenn man eigentlich nach Resume sucht? :gruebel:

Außerdem gehört eine Erklärung in die OH, warum diese sooo gefährlich und nun auch deprecated sind.


[add]
OK, in XE hat man dieses ja nun endlich mal beseitigt. (schön, daß "alte" Versionen so selten geupdatet werde)

Zitat:

...

Setzt die Ausführung eines unterbrochenen Threads fort. Resume sollte von den Debuggern verwendet werden und ist in RAD Studio XE 2010 veraltet.

Mit Resume nehmen Sie die Ausführung eines Thread wieder auf. Suspend-Aufrufe können verschachtelt sein. Entsprechend oft muss dann aber auch Resume aufgerufen werden, bevor der Thread fortgeführt wird.

Mit der Methode Start können Sie die Ausführung eines neu erstellten und angehaltenen Threads aufnehmen.

Warnung: Die Methoden Resume und Suspend sollten nur für das Debuggen verwendet werden. Das Anhalten eines Threads mit Hilfe von Suspend kann zu Deadlocks und undefiniertem Verhalten in der Anwendung führen. Korrekte Thread-Synchronisierungen sollten mit TEvent und TMutex vorgenommen werden.

EWeiss 23. Aug 2011 11:47

AW: W1000 Symbol 'Resume' ist veraltet ????
 
Zitat:

Das würde ich so nicht ganz behaupten.
ja wo steckt denn nun die Lösung in den 3 Zeilen ? :gruebel:

gruss

himitsu 23. Aug 2011 12:02

AW: W1000 Symbol 'Resume' ist veraltet ????
 
Statt .Resume nutzt man jetzt .Start
und .Suspend gibt es nicht mehr ... auch keinen Ersatz dafür.

Zum Anhalten kannst du ein Event, eine CriticalSection oder sonstwas verwenden, welches den Thread an einer definierten Stelle anhält und dir bescheid gibt, wenn angehalten wurde.



OK, es wäre ja schön gewesen, wenn Emba solche Funktionen gleich eingebaut hätte und man es nicht selber implementieren müßte.

EWeiss 23. Aug 2011 12:17

AW: W1000 Symbol 'Resume' ist veraltet ????
 
Zitat:

Statt .Resume nutzt man jetzt .Start
und .Suspend gibt es nicht mehr ... auch keinen Ersatz dafür.
Danke.. Ja das habe ich gelesen.
Geben tut es das schon noch man soll es halt möglichst nicht mehr verwenden.

Einen Ansatz einer möglichen Lösung hat Tryer ja schon gepostet (danke)
Prüfe gerade ob man es für jede auftretende Sitution verwenden kann.

PS:
Das mit Suspend erklärt vielleicht meine sporadisch auftretenden hänger
wenn ich von einem zum anderen Plugin schalte.

Edit:
Also das mit Start kannst auch vergessen auch kein ersatz für Resume.
Zitat:

Erste Gelegenheit für Exception bei $7597B9BC. Exception-Klasse EThread mit Meldung 'Start kann für einen laufenden oder unterbrochenen Thread nicht aufgerufen werden'. Prozess Example.exe (5736)
gruss

sirius 23. Aug 2011 13:07

AW: W1000 Symbol 'Resume' ist veraltet ????
 
Aber bitte auch nicht SuspendThread nehmen. Ist ja nur der API Aufruf, der in TThread.Suspend gekapselt wird. Auch msdn schreibt, dass man SuspendThread nur zum Debuggen nehmen soll. Allerdings steht nirgends etwas darüber, warum man SuspendThread nicht aus dem eigenen Thread heraus aufrufen kann. Dennoch gibt es schönere / andere Methoden:
Delphi-Quellcode:
{ TmyThread }
private
  FHaltEvent:TEvent;

//...

procedure TmyThread.Continue;
begin
  FHaltEvent.SetEvent;
end;

constructor TmyThread.Create(aSuspended: boolean);
begin
  inherited;
  FHaltEvent:=TEvent.Create(nil,true,true,'');
end;

destructor TmyThread.Destroy;
begin
  FHaltEvent.Free;
  inherited;
end;

procedure TmyThread.execute;
begin

  while not terminated do
  begin
    //do something


    SuspendIfHalted;
  end;


end;

procedure TmyThread.Halt;
begin
  FHaltEvent.ResetEvent;
end;

function TmyThread.Halted: boolean;
begin
  result:= FHaltEvent.WaitFor(0) <> wrsignaled;
end;

procedure TmyThread.SuspendIfHalted;
begin
  FHaltEvent.WaitFor(infinite);
end;


procedure TmyThread.Terminate;
begin
  if Halted then FHaltEvent.SetEvent;
  inherited;
end;

Tryer 23. Aug 2011 13:22

AW: W1000 Symbol 'Resume' ist veraltet ????
 
MSDN-Library durchsuchenSuspendThread
Zitat:

To avoid this situation, a thread within an application that is not a debugger should signal the other thread to suspend itself
Genau das mache ich in dem Beispiel. Suspend könnte man dabei an Stelle von SuspenThread genauso gut verwenden und die Warnung ignorieren - da es so halt "richtig" angewendet wird und Deadlocks ausgeschlossen sind.
Die optionale Verwendung von Events oder Sleep hatte ich ja bereits genannt, siehe auch Suspending Thread Execution
Wie auch in der Delphi-Hilfe werden in jedem MSDN-Artikel leider nur Teilaspekte angesprochen.

Grüsse, Dirk

EWeiss 23. Aug 2011 13:28

AW: W1000 Symbol 'Resume' ist veraltet ????
 
So habe mich jetzt mal entgültig für Tryer Vorschlag entschieden.
Es scheint alles so zu funktionieren wie vorher.

Destotrotz muss ich nochmal nerven.

Ich verwende jetzt
Delphi-Quellcode:
if not VisDataThread.Suspended then
  VisDataThread.Halt;

anstelle von
Delphi-Quellcode:
VisDataThread.Suspend;
Delphi-Quellcode:
procedure TVisDataThread.ResumeVis;
var
  p1: PDWORD;
begin

  WaitCounter := 0;
  p1 := FShareMemPointer;
  Inc(p1, 70);
  p1^ := 0;

  if Suspended then
    Continue;
end;
Continue anstelle von Resume.

1 Frage ist "Halt" nicht etwas ungünstig von der namensgebung gewählt?
Eigentlich beendet der Befehlt Halt ja die ganze Anwendung .. (OK hier als Privat deklariert)
Es geht mir aber um die Namensgebung ;)


Delphi-Quellcode:
procedure TVisDataThread.Execute;
const
  _SECOND = 10000000;
var
  qwDueTime: Int64;
  liDueTime: _LARGE_INTEGER;
  ErrMsg: string;
begin

  if VisTimer = 0 then
    Exit;

  // Create a negative 64-bit integer that will be used to
  // signal the timer 1/4 seconds from now.
  qwDueTime := -1 * (_SECOND div 4);

  // Copy the relative time into a LARGE_INTEGER.
  liDueTime.LowPart := DWORD(qwDueTime and $FFFFFFFF);
  liDueTime.HighPart := longint(qwDueTime shr 32);
  if MySetWaitableTimer(VisTimer,                // handle to a timer object
                        TLargeInteger(liDueTime), // when timer will become signaled
                        FDelayMS,                // periodic timer interval
                        nil,                     // pointer to the completion routine
                        nil,                     // data passed to the completion routine
                        False {flag for resume state}) then
    // Following sentences are repeated every FDelayMS interval all the time from initial
    // start up to program end.
    repeat
      // We need to re-adjust timer interval according to the parameter "DelayMS" of vis plug-in.
      // (in case we exchange vis plug-ins)
      if FDelayMSChanged then
      begin
        FDelayMSChanged := False;
        CancelWaitableTimer(VisTimer);
        MySetWaitableTimer(VisTimer, TLargeInteger(liDueTime), FDelayMS, nil,
          nil, False);
      end;

      if WaitForSingleObject(VisTimer, 1000 {1sec}) = WAIT_OBJECT_0 then
      begin
        DoOnVisTimer;
      end else
        Terminate;

      SuspendIfHalted; // Added
    until Terminated
  else
  begin
    ErrMsg := SysErrorMessage(GetLastError);
    ShowErrorMsgBox(ErrMsg);
    Terminate;
  end;
end;
Wenn ich den Thread erstelle

Delphi-Quellcode:
constructor TVisDataThread.Create(var DataReadyMsg: HWND; var MemPointer: Pointer);
begin

  inherited Create(True);

  DriveThreadId := 0;

  FShareMemPointer := GetBufferAddress;
  MemPointer := FShareMemPointer;
  VisTimer := CreateWaitableTimer(nil, False, 'BassVisTimer');
  if VisTimer <> 0 then
  begin
    DataReadyMsg := FDataReadyMsg;
    FDelayMS := 0;
    ModuledelayMs := 0;
    FDelayMSChanged := False;
    FThreadReady := True;
  end;

  LockFlag := TCriticalSection.Create;
end;
erstelle ich eine CriticalSection
Die 2 Frage ist nun wo ist der Unterschied zwischen CriticalSection und EntercriticalSection?
Nicht das selbe?

Wo wäre es dann angebracht wenn nicht das gleiche
EntercriticalSection und LeaveCriticalSection in TVisDataThread.Execute unterzubringen?

Jetzt nicht schimpfen.. Ja ich muss mich mit dem Thema noch mehr beschäftigen :)
War ja bisher nicht nötig da in älteren vers. von Delphi das problem bisher nicht auftrat.

gruss

sirius 23. Aug 2011 13:54

AW: W1000 Symbol 'Resume' ist veraltet ????
 
"Halted" ist eine Funktion, die nur testet ob der Thread angehalten wurde (ich habe mich an die Namen von Tryer gehalten).

In der Methode Terminate muss dies ja überprüft werden, ansonsten führt folgendes zum Deadlock, wenn der Thread im Haltezustand ist:
Delphi-Quellcode:
myThread.Terminate;
myThread.WaitFor; <--- Programm tot
myThread.Free;
Diese Sache benötigts du bei allen Methoden, wo ein Thread schlafen gelegt wird (auch bei Tyrer)


Alle Zeitangaben in WEZ +1. Es ist jetzt 04:15 Uhr.
Seite 2 von 4     12 34      

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