AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Events in TThread

Ein Thema von DocE · begonnen am 6. Okt 2006 · letzter Beitrag vom 6. Okt 2006
Antwort Antwort
Seite 1 von 2  1 2      
DocE

Registriert seit: 25. Mär 2004
108 Beiträge
 
#1

Events in TThread

  Alt 6. Okt 2006, 10:47
Hallo miteinander!

Es stellt sich folgende Problematik:

In einem TThread werte ich Audiosignale aus. Hierzu verwende ich in dem Thread eine Komponente, die die Arbeit übernimmt und ein Ereignis auslöst, sobald der Puffer voll ist. Damit die Events überhaupt abgearbeitet werden, muss ich Application.ProcessMessages in einer Schleife aufrufen.

Das Problem ist, dass es dadurch gelegentlich zu Fehlern kommt, wenn ich im Hauptthread z.B. ein Fenster erzeuge. Der häufigste Fehler ist: "Leinwand/Bild erlaubt kein Zeichnen", selbst wenn ich die Übergabe des Threads an den Hauptthread komplett ausschalte, also der Thread für sich alleine läuft.

Nehme ich das Application.ProcessMessages raus, kommt es zu keinem Fehler mehr, allerdings wird auch das Event nicht mehr abgearbeitet. Es ist also davon auszugehen, dass der Hauptthread durch den Aufruf von Application.ProcessMessages irgendwie beeinflusst wird. Scheinbar sind dies aber nur spezielle Events, da ich in vorherigen Tests z.B. die Verarbeitung von Timer-Events im Hauptthread durch den Aufruf von Application.ProcessMessages in einem anderen Thread ausschließen konnte.

Meine Fragen also:

1. Warum kommt es durch den Aufruf von Application.ProcessMessages im TThread zu einem Problem?
2. Wie kann man das ganze umgehen? Ist MsgWaitForMultipleObjects() evtl. eine Lösung?

Nach meinem Verständnis müsste man den Thread irgendwie dazu bringen, in bestimmten Abständen seine eigene MessageQueue abzuarbeiten, nur wie?


Execute sieht also derzeit so aus:

Delphi-Quellcode:
procedure TAudioThread.Execute;
begin

 (...)

  AudioKomponente := TAudioKomponente.Create(nil);
  AudioKomponente.OnBufferFilled := BufferFilled;

 (...)

  AudioKomponente.Start;

  while not Terminated do
  begin

    sleep(100);
    Application.ProcessMessages;

  end;

  AudioKomponente.Stop;
  AudioKomponente.Free;

end;


Vielen Dank schon mal!


Grüsse
...Doc
  Mit Zitat antworten Zitat
Benutzerbild von chaosben
chaosben

Registriert seit: 27. Apr 2005
Ort: Görlitz
1.358 Beiträge
 
Delphi XE2 Professional
 
#2

Re: Events in TThread

  Alt 6. Okt 2006, 11:11
Ein Zauberwort heißt "Synchronize" (OH). Damit sollten sich einige Probleme erübrigen.
Benjamin Schwarze
If I have seen further it is by standing on the shoulders of Giants. (Isaac Newton)
  Mit Zitat antworten Zitat
xaromz

Registriert seit: 18. Mär 2005
1.682 Beiträge
 
Delphi 2006 Enterprise
 
#3

Re: Events in TThread

  Alt 6. Okt 2006, 11:14
Hallo,

NIEMALS Application.ProcessMessages in einem Thread aufrufen!
Wozu auch? Ein Thread läuft ja neben dem Hauptthread, deshalb werden normalen Events auch ganz normal abgearbeitet.

Wenn Du eine Komponente innerhalb eines Threads erzeugst, dann muss auch die gesamte Kommunikation innerhalb des Threads ablaufen. Zeig mal etwas Code, dann kann findet sich bestimmt eine Lösung.

Gruß
xaromz
I am a leaf on the wind - watch how I soar
  Mit Zitat antworten Zitat
Benutzerbild von Bernhard Geyer
Bernhard Geyer

Registriert seit: 13. Aug 2002
17.171 Beiträge
 
Delphi 10.4 Sydney
 
#4

Re: Events in TThread

  Alt 6. Okt 2006, 11:14
Zitat von chaosben:
Ein Zauberwort heißt "Synchronize" (OH). Damit sollten sich einige Probleme erübrigen.
Abe ein Synchronize ein einem Thread so eingebaut macht den Thread u.U. vollkommen unnötig.
Es ist evtl. besser den Code er bei Application.ProcessMessages bearbeitet wird einfach nochmal als (lokale) Funktion zu kopieren so das nur Win32-API-Aufrufe stattfinden.
Windows Vista - Eine neue Erfahrung in Fehlern.
  Mit Zitat antworten Zitat
DocE

Registriert seit: 25. Mär 2004
108 Beiträge
 
#5

Re: Events in TThread

  Alt 6. Okt 2006, 11:15
Ich denke Synchronize wird das Problem nicht lösen, denn ich möchte ja gar nichts im Hauptthread ausführen. Das Application.ProcessMessages (bzw. die jetzt gesuchte Alternative) soll ja nur dafür sorgen, dass der Thread seine eigenen Events behandelt.

Die Übergabe an den Hauptthread erfolgt dann unter Verwendung von CriticalSections. Die Übergabe ist aber auch nicht das Problem.

Grüsse
...Doc
  Mit Zitat antworten Zitat
DocE

Registriert seit: 25. Mär 2004
108 Beiträge
 
#6

Re: Events in TThread

  Alt 6. Okt 2006, 11:22
Hi Xaromz,

der wichtigeste Teil des Codes ist eigentlich oben gepostet. Die AudioKomponente ruft halt das Ereignis OnBufferFilled auf, sobald der Puffer voll ist. Den Verarbeite ich dann und übergebe ihn ggf. an den Hauptthread.

Das Problem ist ja nur diese Schleife:

Delphi-Quellcode:
  while not Terminated do
  begin

    sleep(100);
    Application.ProcessMessages;

  end;
In dieser Schleife muss irgendetwas anderes passieren (anstatt Application.ProcessMessages) damit der Thread seine "eigenen" Events, hier: OnBufferFilled der AudioKomponente, bearbeiten kann.

Ohne Application.ProcessMessages passiert gar nichts (keine Bearbeitung des Events).


Grüsse
...Doc
  Mit Zitat antworten Zitat
Benutzerbild von chaosben
chaosben

Registriert seit: 27. Apr 2005
Ort: Görlitz
1.358 Beiträge
 
Delphi XE2 Professional
 
#7

Re: Events in TThread

  Alt 6. Okt 2006, 11:25
Zitat von DocE:
denn ich möchte ja gar nichts im Hauptthread ausführen.
Das kann nicht sein. Scheinbar führst du irgendwelche Funktionen aus, die Effekte auf das Aussehen visueller Komponenten haben, die zu dem Hauptthread gehören. Wenn diese "Statusanzeigen" synchronisisert werden, wirst du die damit verbundene Fehlermeldung("Leinwand/Bild erlaubt kein Zeichnen") los und hast trotzdem die Vorteile eines Threads.

Natürlich darfst du nicht die ganze Berechnung synchronisieren, denn dann hätte Bernhard recht.

Und btw.: "BufferFilled" sollte idealerweise eine Prozedur des Threads sein.
Benjamin Schwarze
If I have seen further it is by standing on the shoulders of Giants. (Isaac Newton)
  Mit Zitat antworten Zitat
DocE

Registriert seit: 25. Mär 2004
108 Beiträge
 
#8

Re: Events in TThread

  Alt 6. Okt 2006, 11:30
Die einzige Aktion die ich im Hauptthread ausführe ist die Übergabe an ein Array. Es wird nichts gezeichnet, geupdatet o.ä. Aber, wie bereits gesagt, ist die Übergabe auch nicht das Problem.

BufferFilled ist eine Prozedur des Threads.

Die Fehlermeldung kommt durch das "Application.ProcessMessages" in der Schleife. Selbst wenn die Übergabe an den Hauptthread komplett herausgenommen wird, kommt es zu dem Fehler "Leinwand/Bild erlaubt kein Zeichnen", wenn z.B. im Hauptthread ein Fenster geöffnet wird.

Ich glaube ich mache mal ein einfaches Beispielprogramm fertig...
  Mit Zitat antworten Zitat
Benutzerbild von chaosben
chaosben

Registriert seit: 27. Apr 2005
Ort: Görlitz
1.358 Beiträge
 
Delphi XE2 Professional
 
#9

Re: Events in TThread

  Alt 6. Okt 2006, 11:32
Zitat von DocE:
Ich glaube ich mache mal ein einfaches Beispielprogramm fertig...
Benjamin Schwarze
If I have seen further it is by standing on the shoulders of Giants. (Isaac Newton)
  Mit Zitat antworten Zitat
xaromz

Registriert seit: 18. Mär 2005
1.682 Beiträge
 
Delphi 2006 Enterprise
 
#10

Re: Events in TThread

  Alt 6. Okt 2006, 11:39
Hallo,

Du erstellst im Thread ein Objekt, das Audiodaten verarbeitet und dabei ab und zu einen Event feuert. Auf diesen möchtest Du innerhalb des Events reagieren.

Sehe ich das richtig?

Wenn ja, dann stellt sich die Frage, wie das Objekt die Audiodaten verarbeitet. Wenn das synchron abläuft, sollte die Lösung ungefähr so aussehen:

Delphi-Quellcode:
type
  TAudioThread = class(TThread)
  private
    procedure OnBufferFilled(Sender: TObject);
  public
    procedure Execute; override;
  end;

implementation

procedure TAudioThread.Execute;
var
  AudioKomponente: TAudioKomponente;
begin
  AudioKomponente := TAudioKomponente.Create(nil);
  AudioKomponente.OnBufferFilled := OnBufferFilled;
  AudioKomponente.Start;
  // hier wird periodisch der Event aufgerufen...
  AudioKomponente.Stop;
  AudioKomponente.Free;
end;

procedure TAudioThread.OnBufferFilled(Sender: TObject);
begin
  Tu irgendwas...
end;
Dadurch, dass die Audiokomponente im Thread aufgerufen wird, läuft sie ja schon neben dem Hauptthread, und der Eventhandler wird im Kontext des Threads aufgerufen.

Wenn hingegen die Audiokomponente asynchron läuft, dann hast Du mit einem Thread ein Problem. Aber dann benötigst Du auch keinen.

Gruß
xaromz
I am a leaf on the wind - watch how I soar
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 10:34 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