Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi Thread verursacht Fehler (https://www.delphipraxis.net/11801-thread-verursacht-fehler.html)

Lefko 13. Nov 2003 23:44


Thread verursacht Fehler
 
Hallo Freunde :hi: ,

ich hab ja schonmal einen Thread zum Thema Thread (lol) aufgemacht, da war dann auch alles sahne,
aber jetz hab ich in ein anderes Programm auch einen Thread (TSoundThread) eingebaut.

Komischerweise meldet er mir einen Fehler, den ich nicht verstehe. Wahrscheinlich liegt das daran, dass ich von Threads immernoch zu wenig ahnung habe!

Hier der Code:

Delphi-Quellcode:
unit USoundThread;

interface

uses
  Classes, MMSystem;

type
  TSoundThread = class(TThread)
  protected
    procedure Execute; override;
  public
       { Public declarations }
    constructor Create(Pfad : string);
  end;

implementation

var SoundPfad : Pchar;          <--------- wenn ich SoundPfad in die Private Declaration setze, kommt eine Access Violation, wenn dem etwas zugeordnet wird

{ TSoundThread }

constructor TSoundThread.Create(Pfad : string);
begin
SoundPfad := pchar(Pfad); //hier kommt die AV mit SoundPfad in der P D
FreeOnTerminate := true;  //wenn SoundPfad ne globale Var ist, dann kommt die AV hier...
inherited Create(false);
end;

procedure TSoundThread.Execute;
begin
  { Place thread code here }
  sndPlaySound(SoundPfad,snd_loop); // kann man ne Wave noch anders inner schleife abspielen?
  //if terminated then break;      // <--- das funktioniert nun nämlich nicht mehr...
end;

end.
und so wird der Thread generiert:

Delphi-Quellcode:
procedure TForm3.FormCreate(Sender: TObject);
var SoundThread : TSoundThread;
begin

...

//Musik starten
if FileExists(ExtractFilePath(Paramstr(0)) + 'Optionen') then
    begin
     F := TInifile.Create(ExtractFilePath(Paramstr(0)) + 'Optionen');
     if not F.ReadBool('Optionen','Background', true) then exit;
    end;

Pfad := ExtractFilePath(Paramstr(0)) + 'Sound\Background.wav';

if FileExists(Pfad) then SoundThread.Create(Pfad);
end;
MfG Lefko.

Bernd Ua 14. Nov 2003 00:05

Re: Thread verursacht Fehler
 
Hi,

lass die Finger von den PChars. Das iss nur die Adresse eines Strings.
Wenn Du darin die Adresse eines Parameters oder lokalen Variablen aufhebst,
hast du nix davon ausser dem ungültigen Zeiger und der beobachteten AV.

Also im Abschnitt private deines Threads eine lokale Variable vom String,
dorthin im Konstruktor den Pfad kopieren und erst beim Abspielen auf PChar typecasten.
Dann ist der String wenigstens da :)

In der Execute Methode würde ich ja die klassiche Schleife vorschlagen

Code:
repeat
...
until Terminated
Grüsse Bernd

NicoDE 14. Nov 2003 00:15

Re: Thread verursacht Fehler
 
Zitat:

Zitat von Bernd Ua
dorthin im Konstruktor den Pfad kopieren und erst beim Abspielen auf PChar typecasten.
Dann ist der String wenigstens da :)

Und um zusätzlich alle Zweifel zu beseitigen, kann UniqueString() für die lokale Variable nicht schaden (siehe Delphi-Hilfe).

Luckie 14. Nov 2003 00:17

Re: Thread verursacht Fehler
 
Das was Herr Ua meint, kannst du auch in meinem Threading Tutorial von meiner Seite nachlesen. Desweiteren empfiehlt es sich, den Thread im angehaltenen Zustan zu erzeugen, was hier gar nicht anders geht, alles nötige zu initialisieren, in diesem Fall, die public Varaible für den Thread und ihn dann mit Resume in den zuteilungsfähigen Zustand zu versetzen.

NicoDE 14. Nov 2003 00:30

Re: Thread verursacht Fehler
 
Zitat:

Zitat von Lefko
kann man ne Wave noch anders inner schleife abspielen?

Zum Beispiel mit SND_ASYNC-Flag im Hintergrund abspielen und irgendwann mit SND_PURGE-Flag wieder stoppen.

Hier ein Beispiel mit einer einkompilierten WAV-Ressource mit der ID 1:
Delphi-Quellcode:
  // Play sound
  PlaySound(MakeIntResource(1), HInstance, SND_RESOURCE or SND_LOOP or
    SND_ASYNC);

  // [...]

  // Stop sound
  PlaySound(MakeIntResource(1), HInstance, SND_RESOURCE or SND_PURGE or
    SND_ASYNC or SND_NOWAIT);

Bernd Ua 14. Nov 2003 09:08

Re: Thread verursacht Fehler
 
Hi NicoDE,

Zitat:

Und um zusätzlich alle Zweifel zu beseitigen, kann UniqueString() für die lokale Variable nicht schaden (siehe Delphi-Hilfe).
Eigentlich ab Delphi 5 einschliesslich unnötig, da ab hier IMHO der Increment und Decrement für RefCounter des Strings
über InterlockedIncrement etc gehandelt wird.

Bernd

choose 14. Nov 2003 09:25

Re: Thread verursacht Fehler
 
Zitat:

Zitat von Bernd Ua
Eigentlich ab Delphi 5 einschliesslich unnötig, da ab hier IMHO der Increment und Decrement für RefCounter des Strings
über InterlockedIncrement etc gehandelt wird.

Hallo Bernd. Oberflächlich betrachtet stimmt das, in den Sourcen steht jeweils etwas in der Form
Code:
LOCK DEC [EAX-skew].StrRec.refCnt
trotzdem glaube ich mich erinnern zu können, dass Kudzu auf einer seiner Sessions zu "Indy10" oder "Threads" auf der diesjährigen EKON (zumindest für D5) ebenfalls vor dem unbedachten Gebrauch gewarnt hat.
Im "Indy In Detph" könne ich hierzu auf Anhieb nichts finden (zumal bei Indy ohnehin Wrapper für alle Basistypen verwendet werden).
Leider habe ich die EKON-CD zZt nicht hier, aber irgendwo bei der TMREW-"Cow-Class" ;) müsste das in seinen Slides stehen...

Bernd Ua 14. Nov 2003 09:45

Re: Thread verursacht Fehler
 
Zitat:

Leider habe ich die EKON-CD zZt nicht hier, aber irgendwo bei der TMREW-"Cow-Class" müsste das in seinen Slides stehen...
Grummel - so so , die Teilnehmer haben die CD schon. Die Speaker noch nicht :(
Bernd

Sharky 14. Nov 2003 09:56

Re: Thread verursacht Fehler
 
Hai,

ich verschiebe den Thread mit meiner Nase mal nach ...... ><((((°> *Sonstiges*
Ist dort wohl besser aufgehoben.

choose 14. Nov 2003 10:00

Re: Thread verursacht Fehler
 
Hallo Bernd,

(kam vor(?)letzte Woche) streng genommen warst Du bei der Session, die ich meine, auch nicht anwesend. Vielleicht grenzt das die Suche weiter ein? Heute Abend werde ich das noch einmal recherchieren.

@Lefko: Um es noch einmal zusammenzufassen. Die solltest den Thread Supended kreieren, und vorerst UniqueString verwenden. Außerdem empfiehlt es sich, den Aufruf des geerben Konstruktors als erste Anweisung in der überschriebenen Implementierung aufzurufen. Abschließend im Konstruktor dann Resume aufrufen.

choose 17. Nov 2003 07:53

Re: Thread verursacht Fehler
 
Leider war den EKON-Slides nichts zu entnehmen, weshalb ich Chad angeschrieben habe und erst jetzt seine Antwort posten kann, weil ich dieses WE (ausnahmsweise einmal) nicht im Bureau war ;)

Hier die Anwort:
Zitat:

:: My Question: Do you know about any problems that occur using the
:: default Delphi strings in a multithreaded environment without
:: these wrapper classes? (I believe you said that...)

Yes. You cannot access an unprotected string in ANY Delphi version, but D4 (And I think 5 and maybe even 6) did not have protection in the reference count areas.

Lefko 17. Nov 2003 21:16

Re: Thread verursacht Fehler
 
Zitat:

Zitat von choose
@Lefko: Um es noch einmal zusammenzufassen. Die solltest den Thread Supended kreieren, und vorerst UniqueString verwenden. Außerdem empfiehlt es sich, den Aufruf des geerben Konstruktors als erste Anweisung in der überschriebenen Implementierung aufzurufen. Abschließend im Konstruktor dann Resume aufrufen.

Hi,
ich hab jetzt all die Tipps eingebaut, aber trotzdem kommt es zu einer AV!

hier der Text:

Delphi-Quellcode:
unit USoundThread;

interface

uses
  Classes, MMSystem;

type
  TSoundThread = class(TThread)
  private
    SoundPfad : string;
  protected
    procedure Execute; override;
  public
       { Public declarations }
    constructor Create(Pfad : string);
  end;

implementation

{ TSoundThread }

constructor TSoundThread.Create(Pfad : string);
begin
inherited Create(true);
UniqueString(Pfad);        //Ab hier kommt die AV
SoundPfad := Pfad;
Resume;
//FreeOnTerminate := true;
end;

procedure TSoundThread.Execute;
begin
  { Place thread code here }
  sndPlaySound(PChar(SoundPfad), SND_ASYNC or SND_LOOP);
  //if terminated then break;
end;

end.
Was kann da noch zu Fehlern führen?!

MfG Lefko.

Luckie 17. Nov 2003 21:30

Re: Thread verursacht Fehler
 
Keine Ahnung, was du da machst:
Delphi-Quellcode:
unit Unit2;

interface

uses
  MMSystem, Classes;

type
  TPlayWave = class(TThread)
  private
    { Private-Deklarationen }
  public
    FFilename: String;
    constructor Create(Filename: string);
  protected
    procedure Execute; override;
  end;

implementation

{ TPlayWave }

constructor TPlayWave.Create(Filename: String);
begin
  Inherited create(True);
  FFilename := Filename;
  FreeOnTerminate := True;
  Resume;
end;

procedure TPlayWave.Execute;
begin
  sndPlaySound(PChar(FFilename), SND_ASYNC);
end;

end.
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var
  WaveThread: TPlayWave;
begin
  WaveThread := TPlayWave.Create(ExtractFilepath(Paramstr(0))+ 'Beeth5th.wav');
end;

NicoDE 17. Nov 2003 21:39

Re: Thread verursacht Fehler
 
Zitat:

Zitat von Lefko
Delphi-Quellcode:
constructor TSoundThread.Create(Pfad : string);
begin
  inherited Create(true);
  UniqueString(Pfad);        //Ab hier kommt die AV
  SoundPfad := Pfad;
  Resume;
  //FreeOnTerminate := true;
end;

Es sollte: UniqueString(SoundPfad) heißen und nach der Zuweisung stehen.
Zitat:

Zitat von Lefko
Delphi-Quellcode:
procedure TSoundThread.Execute;
begin
  { Place thread code here }
  sndPlaySound(PChar(SoundPfad), SND_ASYNC or SND_LOOP);
  //if terminated then break;
end;

SND_ASYNC sorgt dafür, dass PlaySound() sofort zurückkehrt und der Sound im Hintergrund abgespielt wird (genau das, was Du willst). Dadurch ist der gesamte Aufwand - es in einen eigenen Thread zu packen - überflüssig.

Lefko 17. Nov 2003 21:42

Re: Thread verursacht Fehler [GELÖST]
 
Hi Luckie :hi: ,

hm, ich Pappnase hab den Thread nur falsch kreiert.... Delphi hat es zwar nicht als Error gekennzeichnet, aber es führte immer zu ner AV.

statt SoundThread := TSoundThread.create(...)
hab ich SoundThread.Create verwendet... :wall:

Naja, so ist das als Noob :roll:


Danke, MfG Lefko.



PS: Da das Prog jetzt geht hab ich ein weiteres Problem festgestellt, zu dessen Beseitigung ich den Code eigentlich extra in den Thread verfrachtet hab...

Ich will mit dem Thread eine Hintergrundmusik abspielen, und dann soll, wenn die Schlange einen Apfel frisst, auch ein Sound abgespielt werden. Wenn dieser abgespielt wird, wird der Hintergrundsound abgebrochen :(

Eigentlich will ich zwei Musikdateien also gleichzeitig abspielen! (Hatte das auch mit einer 2. exe, die nur zum soundabspielen gestartet wurde, das war aber unpraktisch und sehr unelegant...)

Was könnte ich noch machen, damit es funktioniert?!?

Rumpi 17. Nov 2003 22:47

Re: Thread verursacht Fehler
 
Hi,

über das vergessene 'T' und die resultierende AV
bin ich in den letzten Monaten auch mehrmals gestolpert.

mfg Rumpi


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