Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Delphi Thread Queue probleme (https://www.delphipraxis.net/196596-thread-queue-probleme.html)

EWeiss 1. Jun 2018 21:27


Thread Queue probleme
 
Vielleicht kann mir jemand sagen woran es liegt.

Delphi-Quellcode:
function TAudioVolume.OnStateChanged(NewState: uint): HResult;
begin

  if MainThreadID <> GetCurrentThreadId then
  begin
    TThread.Queue(nil,
      procedure
      begin
        if Assigned(FOnSessionStateEvent) then
          FOnSessionStateEvent(self, NewState);
      end);
  end;

  Result := S_OK;
end;
Delphi-Quellcode:
procedure TMainClass.SessionStateEvent(Sender: TCustomAudioVolume; NewState: integer);
var
  I, K: integer;
  ProcId: DWORD;
  vProcList: TProcesses;
  bFound: BOOL;
begin

  bFound := false;

  for I := 0 to Length(AudioVolumeArr) - 1 do
  begin
    if AudioVolumeArr[I] = Sender then
      break;
  end;

  ProcId := StrToInt(AudioVolumeArr[i].AudioSessionInfo(I).ProcessID);

  if (ProcId <> 0) and (NewState = 0) then
  begin
    // ProcList initialisieren
    vProcList := TProcesses.Create;
    // Prozesse einlesen
    vProcList.ReadSystem;
    // prüfen ob aktiver prozess existiert
    for K := 0 to vProcList.Count-1 do
      if vProcList[K].ID = ProcId then
      begin
        bFound := true;
        // Raus hier
        break;
      end;

    if not bFound then
    begin
      // Timer deaktivieren
      Killtimer(HSprMaster, ID_MRENDER);
      // Alle Objekte die mit diesen verbunden sind löschen
      for I := 0 to Length(AudioVolumeArr) - 1 do
        gSprSession.GD_DeleteLinkedObject(succ(ID_BVOLUME) + i);
      // Array löschen
      Setlength(AudioVolumeArr, 0);
      // Session erstellen
      CreateSession;
      // Window aktualisieren
      gSprSession.GI_UpdateWindow(HSprSession, false);
      // Timer aktivieren
      SetTimer(HSprMaster, ID_MRENDER, 60, nil);
      // Prozessliste löschen und freigeben
      vProcList.Clear;
      FreeAndNil(vProcList);
    end;
  end;
end;
Vorher habe ich TThread.Synchronize verwendet das hat die weitere Verarbeitung von anderen Dingen im Main Thread geblockt.
Jetzt verwende ich statt dessen TThread.Queue

Ich kann jetzt das alte control löschen und die Sessions neu erstellen.
Mein Problem ist aber das da anscheinend immer noch was blockt oder durcheinander bringt, was auch immer bekomme diese Fehlermeldung sobald ich auf eine Funktion von TAudioVolume zugreife.
Ich weis nicht was falsch läuft und wie ich das verhindern\beheben kann.

Zitat:

EInvalidPointer with message 'Invalid pointer operation'.
sehr oft..

gruss

EWeiss 2. Jun 2018 09:55

AW: Thread Queue probleme
 
Von mehr als 61918 + die nach mir gefolgten Foren Mitgliedern.
Ist niemand in der Lage mir auf meine Frage eine Antwort zu geben?
Schwach wirklich! ;) :duck:

Es muss doch eine Möglichkeit geben den Thread zu synchronisieren auch wenn ich nicht auf die Rückgabe warte.
Queue >= PostMessage
Synchronize >= SendMessage


gruss

KodeZwerg 2. Jun 2018 11:46

AW: Thread Queue probleme
 
Ich bin bestimmt wieder völlig falsch aber vielleicht meinst Du WaitForSingleObject bzw WaitForMultipleObjects um innerhalb threads so etwas wie einen Fortschritt zu registrieren?

mkinzler 2. Jun 2018 11:54

AW: Thread Queue probleme
 
Zitat:

Von mehr als 61918 + die nach mir gefolgten Foren Mitgliedern.
Ist niemand in der Lage mir auf meine Frage eine Antwort zu geben?
Schwach wirklich!
Das kommt auch auf die Erwartungshaltung an! Das ist ein Forum mit freiwilligen Helfern und kein kommerzielles Supportforum wöfur man Blechen muss! Und selbst dann könntest Du nicht erwarten, dass eine am späten Freitag abend gestellt Frage bis Samsatg Mittag beantwortet wird!

KodeZwerg 2. Jun 2018 12:03

AW: Thread Queue probleme
 
Hier ist ein Beispiel wo ich einen Thread starte aber nicht direkt auf sein Ende warte.
entfernt da es nicht beim Problem hift.

EWeiss 2. Jun 2018 12:08

AW: Thread Queue probleme
 
Das hat absolut nichts mit meinem Problem zu tun .. trotzdem Dank für den Versuch.
Es geht um die Synchronisierung nicht darum auf etwas zu warten.
Ich habe keinen Einfluss auf das Event und wenn das gefeuert wird gibt es nix zu warten.

Dann muss ich handeln.

gruss

KodeZwerg 2. Jun 2018 12:34

AW: Thread Queue probleme
 
Ich hoffe einer dieser Links zeigt es Dir richtig an.
Unterschied TTread.Synchronize / TThread.Queue oder Delphi Queue and Synchronize

EWeiss 2. Jun 2018 12:39

AW: Thread Queue probleme
 
Zitat:

Zitat von KodeZwerg (Beitrag 1403690)
Ich hoffe einer dieser Links zeigt es Dir richtig an.
Unterschied TTread.Synchronize / TThread.Queue oder Delphi Queue and Synchronize

Ich weis was Queue and Synchronize ist das hatte ich bereits gepostet.
Siehe!

Queue >= PostMessage (Wenn ich nicht warte kommt der unten aufgeführte Fehler)
Synchronize >= SendMessage (Wenn ich warte kann ich keine UI mehr erstellen in welcher Form auch immer)

Im Grunde nichts anderes aber selbst wenn ich es weis behebt es nicht mein momentanes Problem
das ich nach dem Event nicht mehr auf TAudioVolume zugreifen kann ohne die besagte Fehlermeldung zu bekommen.
Zitat:

EInvalidPointer with message 'Invalid pointer operation'.
Also nochmal zur Verdeutlichung.

Ich kann User Interface erstellen wenn ich Queue verwende aber es wirft mir die Pointer durch die Gegend.
Das ist mein Problem!

Synchronize funktioniert nicht weil hier auf eine Rückgabe gewartet wird und das erstellen von User Interface unmöglich ist im Main Thread.

gruss

Zacherl 2. Jun 2018 13:07

AW: Thread Queue probleme
 
Kannst du da denn nicht mal genauer reinsteppen mit dem Debugger und eine genaue Stelle nennen, an der es zum ersten Mal kracht nach dem Event? Btw.: Ich glaube du leakest den Speicher von
Delphi-Quellcode:
vProcList
, falls
Delphi-Quellcode:
bFound = True
.

dummzeuch 2. Jun 2018 13:13

AW: Thread Queue probleme
 
Hast Du schon ermittelt, welche Speicherfreigabe die Exception auslöst? Wenn ja, mal im ensprechenden Destructor einen Breakpoint setzen und schauen, von wo und wie oft er aufgerufen wurde.

EWeiss 2. Jun 2018 13:14

AW: Thread Queue probleme
 
Zitat:

Zitat von Zacherl (Beitrag 1403694)
Ich glaube du leakest den Speicher von
Delphi-Quellcode:
vProcList
, falls
Delphi-Quellcode:
bFound = True
.

Auf jeden fall ist das so.

Beim beenden der Anwendung bekomme ich ein Speicherleck Meldung von der vProcList angezeigt.
Glaube aber das ist deshalb weil die Pointer verschoben werden wie oder wo auch immer.

Denn ich gebe die ja frei FreeAndNil(vProcList);
Aber es fruchtet nicht die Speicherlecks kommen trotzdem.

Zitat:

Kannst du da denn nicht mal genauer reinsteppen mit dem Debugger und eine genaue Stelle nennen, an der es zum ersten Mal kracht nach dem Event?
Es kracht sobald ich irgendwo wieder auf TAudioVolume zugreife.
Die Zeile ist diese aber die macht nichts besonderes was den Fehler auslösen könnte.

Delphi-Quellcode:
function TAudioVolume.AudioSessionInfo(SessionIndex: integer): TAudioSessionInfo;
var
  Lbl: TLabel;
  tmpStr: string;
  bNull: BOOL;
  i: integer;
begin
  Result.ActiveSession := '';
  Result.DisplayName := '';
  Result.StateSession := '';
  Result.IconPath := '';
  Result.SessionIdentifier := '';
  Result.ProcessID := '';
  Result.IsSystemSoundsSession := -1;
  Result.SessionGuid := StringToGUID('{00000000-0000-0000-0000-000000000000}');
  Result.Device := nil;
  Result.PID := 0;

  bNull := False;

  tmpStr := ExtractFileExt(FAudioSessionInfo.DisplayName); \\ <<<<<<< Hier kracht es
  if Length(tmpStr) > 1 then
    tmpStr := ChangeFileExt(FAudioSessionInfo.DisplayName, '')
  else
    tmpStr := FAudioSessionInfo.DisplayName;
Ok ;)
FreeAndNil(vProcList); steht an falscher stelle muss eine Zeile tiefer. Danke.
Werde mal schauen ob das mein Problem behebt.

Die Leaks sind behoben aber das Problem bleibt bestehen.
Habe nur diese beiden. Siehe Anhang.


gruss

mkinzler 2. Jun 2018 13:18

AW: Thread Queue probleme
 
Zitat:

Denn ich gebe die ja frei FreeAndNil(vProcList);
Aber nur, wenn du den Prozess vorher nicht gefunden hast, sonst nicht.

EWeiss 2. Jun 2018 13:23

AW: Thread Queue probleme
 
Zitat:

Zitat von mkinzler (Beitrag 1403697)
Zitat:

Denn ich gebe die ja frei FreeAndNil(vProcList);
Aber nur, wenn du den Prozess vorher nicht gefunden hast, sonst nicht.

Richtig. .Danke!
Deshalb habe ich sie eine Zeile tiefer gesetzt Fehler ist behoben was die Leaks betrifft.
Die Pointer spielen aber immer noch verrückt.

Die anderen Speicherlecks.. siehe Shots.

gruss

EWeiss 2. Jun 2018 13:57

AW: Thread Queue probleme
 
Zitat:

Zitat von dummzeuch (Beitrag 1403695)
Hast Du schon ermittelt, welche Speicherfreigabe die Exception auslöst? Wenn ja, mal im ensprechenden Destructor einen Breakpoint setzen und schauen, von wo und wie oft er aufgerufen wurde.

Keine Speicherfreigabe löst den Fehler aus.
Sondern der nächste darauffolgende zugriff auf TAudioVolume.

gruss

KodeZwerg 2. Jun 2018 18:14

AW: Thread Queue probleme
 
Ich liege hundert pro eh falsch aber gesagt haben mag ichs mal.
Setze doch mal einen BP vor Zeile
Delphi-Quellcode:
FOnSessionStateEvent(self, NewState);
und stepp dich da mal rein ob das alles seine Richtigkeit hat. Noch kommt mir das Self komisch vor, aber ich kann mich, wie so oft bei Dir, total irren.

Und verträgt Result.IsSystemSoundsSession :-1; einen negativen Wert ?

Zitat:

tmpStr := ExtractFileExt(FAudioSessionInfo.DisplayName); \\ <<<<<<< Hier kracht es
existiert denn FAudioSessionInfo.DisplayName zu diesem Zeitpunkt?
Wegen Result.DisplayName := '';
Lass Dir doch an dieser Stelle ne MessageBox anzeigen was du da so für Daten im Speicher hast.

EWeiss 2. Jun 2018 20:41

AW: Thread Queue probleme
 
bekomme es nicht geregelt. egal.
Habe noch andere Projekte.

gruss

Zacherl 3. Jun 2018 17:39

AW: Thread Queue probleme
 
Wenn du doch nochmal reinschauen willst: Was sagt denn der Debugger zu den Werten von
Delphi-Quellcode:
Self
,
Delphi-Quellcode:
FAudioSessionInfo
, etc? Steht da unter Umständen vielleicht schon "Müll" drinnen? Nur mit statischen Informationen ist es hier leider recht schwer die Fehlerquelle zu ermitteln.

EWeiss 3. Jun 2018 17:42

AW: Thread Queue probleme
 
Zitat:

Zitat von Zacherl (Beitrag 1403756)
Wenn du doch nochmal reinschauen willst: Was sagt denn der Debugger zu den Werten von
Delphi-Quellcode:
Self
,
Delphi-Quellcode:
FAudioSessionInfo
, etc? Steht da unter Umständen vielleicht schon "Müll" drinnen? Nur mit statischen Informationen ist es hier leider recht schwer die Fehlerquelle zu ermitteln.

Nein self ist die TAudioVolume Classe da steht kein Müll drin.

self und AudioSessionInfo siehe Anhang.
Ist schade aber so kann ich das Projekt nicht fertig stellen. sorry.
Ich habe zu wenig Erfahrung mit Threads so das ich den Fehler selber analysieren könnte.
Der Debugger ist in dem Fall nicht Hilfreich.

Ganz umsonst war das Projekt nicht habe 1>2 Fehler in meiner Library beheben können und eine neue Funktion addiert um zu vor erstellte
Kombinierte Objekte in einem rutsch zu löschen.

Delphi-Quellcode:
// Alle Objekte die mit diesen verbunden sind löschen
for I := 0 to Length(AudioVolumeArr) - 1 do
  gSprSession.GD_DeleteLinkedObject(succ(ID_BVOLUME) + i); // neue Funktion
EDIT:
Habe meine Funktion nochmal optimiert ändert aber nichts an meinem Pointer Problem doch das hier (AudioVolumeArr[M].Free;)
Delphi-Quellcode:
procedure TMainClass.SessionStateEvent(Sender: TCustomAudioVolume; NewState: integer);
var
  IntI, K, M: integer;
  ProcId: DWORD;
  vProcList: TProcesses;
  bFound: BOOL;
begin

  bFound := false;

  for IntI := 0 to Length(AudioVolumeArr) - 1 do
  begin
    if AudioVolumeArr[IntI] = Sender then
    begin
      ShowMessage(AudioVolumeArr[IntI].AudioSessionInfo(IntI).DisplayName + #13#10 +
        'Index ' + IntToStr(IntI) + ' hat jetzt State ' + IntToStr(NewState));

      ProcId := StrToInt(AudioVolumeArr[IntI].AudioSessionInfo(IntI).ProcessID);

      if (ProcId <> 0) and (NewState = 0) then
      begin
        // ProcList initialisieren
        vProcList := TProcesses.Create;
        // Prozesse einlesen
        vProcList.ReadSystem;
        // prüfen ob aktiver prozess existiert
        for K := 0 to vProcList.Count - 1 do
          if vProcList[K].ID = ProcId then
          begin
            bFound := true;
            // Raus hier
            break;
          end;

        if not bFound then
        begin
          // Timer deaktivieren
          KillTimer(HSprMaster, ID_MRENDER);
          // Alle Objekte die mit diesen verbunden sind löschen
          for M := 0 to Length(AudioVolumeArr) - 1 do
          begin
            gSprSession.GD_DeleteLinkedObject(succ(ID_BVOLUME) + M);
            // TAudioVolume freigeben
            AudioVolumeArr[M].Free;
          end;
          // Array löschen
          SetLength(AudioVolumeArr, 0);
          // Session erstellen
          CreateSession;
          // Window aktualisieren
          gSprSession.GI_UpdateWindow(HSprSession, false);
          // Timer aktivieren
          SetTimer(HSprMaster, ID_MRENDER, 60, nil);
        end;
        // Prozessliste löschen
        vProcList.Clear;
        // Prozessliste freigeben
        FreeAndNil(vProcList);
      end;
    end;
  end;
end;
gruss

Zacherl 3. Jun 2018 19:57

AW: Thread Queue probleme
 
Ahchso, ne ich meinte eigentlich das
Delphi-Quellcode:
Self
innerhalb von
Delphi-Quellcode:
TAudioVolume.AudioSessionInfo
. Also dann, wenn es kracht. Meine Vermutung war halt, dass hier schon irgendwelche Zeiger (vlt. sogar
Delphi-Quellcode:
Self
) ins leere laufen.

EWeiss 3. Jun 2018 20:05

AW: Thread Queue probleme
 
Zitat:

Zitat von Zacherl (Beitrag 1403760)
Ahchso, ne ich meinte eigentlich das
Delphi-Quellcode:
Self
innerhalb von
Delphi-Quellcode:
TAudioVolume.AudioSessionInfo
. Also dann, wenn es kracht. Meine Vermutung war halt, dass hier schon irgendwelche Zeiger (vlt. sogar
Delphi-Quellcode:
Self
) ins leere laufen.

Es gibt kein self innerhalb TAudioSessionInfo.
TAudioSessionInfo ist ein Record.

Vielleicht bin ich auch zu dumm zu verstehen was du meinst. ;)
Habe bald den Eindruck als wenn die AudioSes.dll (Win7) selbst fehlerhaft ist wenn hier schon ein Speicherleck angezeigt wird.

gruss

EWeiss 3. Jun 2018 21:58

AW: Thread Queue probleme
 
Hat sich erledigt..
Man achte auf den Unterschied :wall: :duck:

Delphi-Quellcode:
         
for M := 0 to Length(AudioVolumeArr) - 1 do
begin
  gSprSession.GD_DeleteLinkedObject(succ(ID_BVOLUME) + M);
  // TAudioVolume freigeben
  AudioVolumeArr[M].Free;
end;
Delphi-Quellcode:
     
for I := 0 to Length(AudioVolumeArr) - 1 do
  gSprSession.GD_DeleteLinkedObject(succ(ID_BVOLUME) + i);
War so auf das Grafik Objekt fixiert das ich gar nicht bemerkt habe das die dazugehörige Klasse nicht freigegeben wurde.
Manchmal ist man einfach nur blöde.

gruss


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