Delphi-PRAXiS

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)

RaSoWa1 28. Mär 2010 12:01


W1000 Symbol 'Resume' ist veraltet ????
 
Hallo,

bei einem Projekt in dem ich Threads verwende kommt jetzt mit D 2010 folgende Warnung:
Zitat:

[DCC Warnung] ClassAlbum.pas(2068): W1000 Symbol 'Resume' ist veraltet
Lt. Online-Hilfe soll zum Start des Threads aber Resume verwendet werden.

Ist das ein Bug in D 2010?

Gruß Klaus.

himitsu 28. Mär 2010 12:11

Re: W1000 Symbol 'Resume' ist veraltet ????
 
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;
Was ein Blick in die Sourcen so leisten kann. :angel2:

daywalker9 28. Mär 2010 12:11

Re: W1000 Symbol 'Resume' ist veraltet ????
 
Also wenn man bei Delphi selber guckt, steht dies im Source:
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;

RaSoWa1 28. Mär 2010 13:02

Re: W1000 Symbol 'Resume' ist veraltet ????
 
Danke an euch.

Also ein Bug der Online-Hilfe.
Denn da steht:
Zitat:

Classes.TThread.Create
.....
Mit Create erzeugen Sie einen Thread in einer Anwendung. Wenn CreateSuspended den Wert false hat, wird Execute sofort aufgerufen. Andernfalls erfolgt der Aufruf erst nach einem Aufruf von Resume.
aber auch:
Zitat:

Classes.TThread.Start
......
Beginnt die Ausführung eines Threads.

Rufen Sie Start auf, um das Ausführen eines im unterbrochenen Status erzeugten Threads zu starten. Um ein Thread im unterbrochenen Status zu erzeugen, übergeben Sie true an den Konstruktor des Threads. Für die Threads, die im unterbrochenen Status nicht erzeugt wurden, hat Start keine Auswirkung.

Anmerkung: Die Methode Resume ist veraltet und seine Verwendung soll vermieden werden. Verwenden Sie stattdessen die Methode Start.
Gruß Klaus.

EWeiss 22. Aug 2011 20:22

AW: W1000 Symbol 'Resume' ist veraltet ????
 
Ich sehe Suspend ist veraltet...
aber was verwenden an stelle dessen?

Werde aus euren Beiträgen nicht so richtig schlau.

OK für Resume nehme ich Start..
aber für Suspend ?

EDIT:
Terminate?

gruss

Tryer 22. Aug 2011 20:39

AW: W1000 Symbol 'Resume' ist veraltet ????
 
Suspend sollte man ganz vermeiden, da man nie wissen kann in welchem Augenblick man den Thread damit erwischt - schwer zu findende Deadlocks sind so vorprogrammiert. Besser Terminate oder ein eigenes Flag(Boolean/Event/Semaphore..) verwenden um den Thread ggf. an einer kontrollierten Stelle warten zu lassen.

EWeiss 22. Aug 2011 21:01

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

Zitat von Tryer (Beitrag 1118715)
Suspend sollte man ganz vermeiden, da man nie wissen kann in welchem Augenblick man den Thread damit erwischt - schwer zu findende Deadlocks sind so vorprogrammiert. Besser Terminate oder ein eigenes Flag(Boolean/Event/Semaphore..) verwenden um den Thread ggf. an einer kontrollierten Stelle warten zu lassen.

Wenn ich so wie vorgeschlagen Suspend mit Terminate ersetze..
bzw. Resume mit Start dann geht bei mir gar nichts mehr.

Hmmmm ... Dann besser so belassen und mit den Warnungen leben?

gruss

Tryer 22. Aug 2011 22:01

AW: W1000 Symbol 'Resume' ist veraltet ????
 
Hmm.. wenn property Terminated wie in älteren Versionen ReadOnly ist und .Start das scheinbar auch nicht zurücksetzt ist es natürlich keine Lösung - dann kann man den Thread auch freigeben und einen neuen erzeugen.. das Konzept scheint mal wieder sehr gut durchdacht zu sein :?

Idee:
Delphi-Quellcode:
type
  TMyThread = class(TThread)
  private
    FHalted: Boolean;
    procedure SuspendIfHalted;
  public
    procedure Halt;
    procedure Continue;
  end;

  procedure TMyThread.Halt;
  begin
    FHalted := True;
  end;

  procedure TMyThread.Continue;
  begin
    FHalted := False;
    ResumeThread(Handle);
  end;

  procedure TMyThread.SuspendIfHalted;
  begin
    if FHalted then
      SuspendThread(Handle);
  end;

  procedure TMyThread.Execute;
  begin
    repeat
      EntercriticalSection;
      ..
      LeaveCriticalSection;
      ..
      //sichere Warteposition ausserhalb Lock
      SuspendIfHalted;
    until Terminated;
  end;
Zu jedem "Terminate" gehört dann natürlich ein "Continue" um den Thread ggf. aufzuwecken.

Alternativ zu SuspendIfHalted ohne echtes Suspend-/ResumeThread:
Delphi-Quellcode:
while FHalted and not Terminated do Sleep(10);


Grüsse, Dirk

EWeiss 22. Aug 2011 22:25

AW: W1000 Symbol 'Resume' ist veraltet ????
 
Danke für dein Beispiel .. Werde mir das mal anschauen in Ruhe.

Mein Problem ist folgendes
Delphi-Quellcode:
  procedure TMyThread.Execute;
  begin
    repeat
      EntercriticalSection;
      ..
      LeaveCriticalSection;
      ..
      //sichere Warteposition ausserhalb Lock
      SuspendIfHalted;
    until Terminated;
  end;
So wie hier wartest du auch auf Terminate..
Der Thread läuft also so lange bis der Zustand Terminate eintritt.

Wenn ich nun anstelle von Suspend.. Terminate verwende so wie vorgeschlagen
dann beendet sich logischerweise der Thread das hat zur folge das ich anschließend kein Plugin mehr starten kann.

MeinThread.Suspend hält den Thread ja nur an und beendet ihn nicht so wie Terminate das tut.

Damit stehe ich im Konflikt zu der Aussage anstelle von Suspend! Terminate zu verwenden.
Na ja und wie MeinThread.Start im vergleich zu MeinThread.Resume steht das ist auch noch fraglisch.

gruss

Tryer 22. Aug 2011 22:32

AW: W1000 Symbol 'Resume' ist veraltet ????
 
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

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)

EWeiss 23. Aug 2011 14:03

AW: W1000 Symbol 'Resume' ist veraltet ????
 
Danke sirius hab meinen Beitrag nochmal editiert.
Komme mit einigen sachen noch nicht ganz klar

gruss

sirius 23. Aug 2011 14:30

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

Zitat von Tryer (Beitrag 1118965)
Wie auch in der Delphi-Hilfe werden in jedem MSDN-Artikel leider nur Teilaspekte angesprochen.

Und so ein Teilaspekt ist halt auch folgender:
(Suche nach "SuspendThread race condition")
Zitat:

The reason is related to a possible race condition with the suspend count.
The suspend count is incremented by a call to SuspendThread(), and is
decremented by a call to ResumeThread(). If the suspend count is non-zero,
then the scheduler will mark the thread as "waiting" (or not ready), and
will not schedule the thread for processing; conversely, when the suspend
count is exactly zero, the thread is marked as "ready" and is given
processing time. The race condition occurs because access to the suspend
count is not synchronized between threads, such that it is possible for one
thread to decrement the suspend count beyond zero to a value of -1. At that
value, the thread will never be scheduled for processing.


EWeiss 23. Aug 2011 14:34

AW: W1000 Symbol 'Resume' ist veraltet ????
 
Kann sich nochmal bitte jemand dieser Frage annehmen?
http://www.delphipraxis.net/1118970-post19.html

gruss

sirius 23. Aug 2011 14:44

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

Zitat von EWeiss (Beitrag 1119006)
Kann sich nochmal bitte jemand dieser Frage annehmen?
http://www.delphipraxis.net/1118970-post19.html

gruss

1. Such dir halt einen Namen aus (suspend ist ja leider schon vergeben; genauso: break und interrupt) Stop wäre noch übrig. Aber dann neigt man beim weitermachen dazu start zu verwenden, was ja schon vergeben ist. Das Antonym für continue ist ja discontinue. Gibts aber zumindest in meinem aktiven Wortschatz bisher nicht. Naja, lass dir was einfallen....

2. CriticalSection ist ein Handle-Objekt. EnterCriticalSection ist eine Funktion auf dieses Handle-Objekt.
TCriticalSection ist eine Klasse, welches das Handle-Objekt CriticalSection kapselt. TCriticalsection.EnterCriticalSection ist eine Methode vorheriger Klasse.
Was war eigentlich genau deine Frage?

Deine 3. Frage verstehe ich nicht.

EWeiss 23. Aug 2011 14:49

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

2. CriticalSection ist ein Handle-Objekt. EnterCriticalSection ist eine Funktion auf dieses Handle-Objekt.
TCriticalSection ist eine Klasse, welches das Handle-Objekt CriticalSection kapselt. TCriticalsection.EnterCriticalSection ist eine Methode vorheriger Klasse.
Habe dann wohl was falsch gemacht. :oops:
Dann habe ich zwar das Handle object erstellt aber keine Function welche das handle verwaltet (bzw. damit arbeitet)

Die Frage war ..
An welcher stelle ist es sinnvoll EntercriticalSection und LeaveCriticalSection in TVisDataThread.Execute unterzubringen?

wo könnte hier etwas Kritisch sein das ich EntercriticalSection verwenden muss, sollte?
Muss mal bei MS lesen wofür EntercriticalSection genau steht ;)
Verstehe die Anwendung der Function wohl noch nicht!

gruss

sirius 23. Aug 2011 14:54

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

Zitat von EWeiss (Beitrag 1119013)
Die Frage war ..
An welcher stelle ist es sinnvoll EntercriticalSection und LeaveCriticalSection in TVisDataThread.Execute unterzubringen?

wo könnte hier etwas Kritisch sein das ich EntercriticalSection verwenden muss, sollte?

Dazu eine Frage:
Welche Variablen in Execute verwendest du auch außerhalb des Threads (und zwar in dem Moment, wo der Thread läuft)?

Tryer 23. Aug 2011 15:03

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

The race condition occurs because access to the suspend
count is not synchronized between threads, such that it is possible for one
thread to decrement the suspend count beyond zero to a value of -1.
Da ausschliessliuch der Thread selber SuspendCount verringert seh ich darin kein Problem - auch wieder ein Fall wo nur das Suspend aus einem anderen Thread zum Fehler führt.

EWeiss 23. Aug 2011 15:06

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

Zitat von sirius (Beitrag 1119017)
Zitat:

Zitat von EWeiss (Beitrag 1119013)
Die Frage war ..
An welcher stelle ist es sinnvoll EntercriticalSection und LeaveCriticalSection in TVisDataThread.Execute unterzubringen?

wo könnte hier etwas Kritisch sein das ich EntercriticalSection verwenden muss, sollte?

Dazu eine Frage:
Welche Variablen in Execute verwendest du auch außerhalb des Threads (und zwar in dem Moment, wo der Thread läuft)?

FDelayMSChanged
FDelayMSChanged wird aufgerufen wenn ein neues Plugin gestartet wird und die ms sich geändert haben.

ps..
ist aber vom gleichen Thread

Delphi-Quellcode:
procedure TVisDataThread.SetDelayMS(delayMs: DWORD);
var
  tmpDelayMS: DWORD;
begin

  tmpDelayMS := delayMs;
  if tmpDelayMS < 10 then
    tmpDelayMS := 10;
  if tmpDelayMS <> FDelayMS then
  begin
    if FDelayMS <> 0 then
      FDelayMSChanged := True;
    FDelayMS := tmpDelayMS;
  end;
end;
gruss

sirius 23. Aug 2011 15:11

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

Zitat von Tryer (Beitrag 1119022)
Zitat:

The race condition occurs because access to the suspend
count is not synchronized between threads, such that it is possible for one
thread to decrement the suspend count beyond zero to a value of -1.
Da ausschliessliuch der Thread selber SuspendCount verringert seh ich darin kein Problem - auch wieder ein Fall wo nur das Suspend aus einem anderen Thread zum Fehler führt.

Eben nicht.
Dieses Problem tritt auf, wenn TmyThread Suspend aufruft und der MainThread gleichzeitig Resume aufruft, was bei deinem Code durchaus passieren kann.


Zitat:

Zitat von Emil
FDelayMSChanged
FDelayMSChanged wird aufgerufen wenn ein neues Plugin gestartet wird und die ms sich geändert haben.

Dann must du um jeden Zugriff (eigentlich nur, wenn mindestens ein Thread auch schreibend darauf zugreift) EnterCriticalSection und LeaveCriticalSection basteln (und zwar von der exakt gleichen Objektinstanz)
Allerdings hast du hier eine Variable allersimplesten Datentypes. Da reichen die interlocked-Funktionen aus und die synchronisation kann entfallen.

EWeiss 23. Aug 2011 15:15

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

Allerdings hast du hier eine Variable allersimplesten Datentypes. Da reichen die interlocked-Funktionen aus und die synchronisation kann entfallen.
Was bedeutet das ich LockFlag sowie EnterCriticalSection gar nicht verwenden muss?

Mir ging es eigentlich darum eventuelle hänger beim umschalten auf andere Plugins zu vermeiden.
Dafür scheint dann wohl EnterCriticalSection nicht das richtige zu sein.

Hab dann wohl was falsch verstanden..

Danke für deine Hilfe

gruss

sirius 24. Aug 2011 08:58

AW: W1000 Symbol 'Resume' ist veraltet ????
 
Ich weis grad nicht, wie speziell ich darauf antworten soll.
Für Threads gibt es keine 0815 Lösung. Es gibt ein paar Möglichkeiten, wie man so etwas gestalten kann (z.B. WorkerThread oder ThreadPool, ...) aber du musst es immer speziell an deine Aufgabe anpassen.

Die Verwendung einer Critical Section geht am besten über eine Klasse:
Delphi-Quellcode:
//Beispiel aus der aktuellen Version (2.03) von TDosCommand

TSyncString=class(TSimpleRWSync)
//TSimpleRWSnyc benutzt intern TCriticalSection
  private
    FValue:String;
    procedure setValue(Value:String);
    function getValue:String;
  public
    function length:Integer;
    property Value:String read getValue write SetValue;
    procedure Add(Value:String);
    procedure Delete(Pos,Count:Integer);
  end;



{ TSyncString }

procedure TSyncString.Add(Value: String);
begin
  BeginWrite; // =EnterCriticalSection
  try
    FValue:=FValue+Value;
  finally
    EndWrite; //=LeaveCriticalSection
  end;
end;

procedure TSyncString.Delete(Pos, Count: Integer);
begin
  BeginWrite; // =EnterCriticalSection
  try
    system.Delete(FValue,Pos,Count);
  finally
    EndWrite; //=LeaveCriticalSection
  end;
end;

function TSyncString.getValue: String;
begin
  BeginRead; // =EnterCriticalSection
  try
    result:=FValue;
  finally
    EndRead; //=LeaveCriticalSection
  end;
end;

function TSyncString.length: Integer;
begin
  BeginRead; // =EnterCriticalSection
  try
    result:=system.length(FValue);
  finally
    EndRead; //=LeaveCriticalSection
  end;
end;

procedure TSyncString.setValue(Value: String);
begin
  BeginWrite; // =EnterCriticalSection
  try
    FValue:=Value;
  finally
    EndWrite; //=LeaveCriticalSection
  end;
end;
Da hier in jeder Methode das gleiche (von der Elternklasse benutzte) Critical-Section-Objekt benutzt wird, kann nur ein einziger Thread in einer der Methoden (zwischen BeginXXX und EndXXX) sein. Wenn gleichzeitig ein anderer Thread auf den String zugreifen will muss er bei BeginXXX warten bis der andere Thread fertig ist.

Diese Klasse kann jetzt in jedem Thread benutzt werden und es gibt keine Synchronisationsprobleme. so benutzt man CriticalSections am besten.
Aber neben CriticalSections gibt es noch eine ganze Reihe anderer Synchronisationsmöglichkeiten (darüber könnte man ein Buch schreiben, was es womöglich auch schon gibt). Die alle aufzulisten und zu erklären würde den Rahmen hier sprengen.
Was du für deine booleanVariable noch wissen solltest sind aber die interlocked-Funktionen. Da hat Windows (eigentlich die Intel-Architektur) eine nette Sache, das für das Ändern eines 32bit Wertes kann man (allerdings an jeder Stelle, wo man den Wert schreibend ändert) interlockedAdd, interlockedExchange,... verwenden. Suche einfach mal nach den Funktionen.


Alle Zeitangaben in WEZ +1. Es ist jetzt 14:08 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