Lauter interessante Vorschläge. Ich verwende nun Queue als vielleicht einfachste Lösung. Klar ist mir, dass die Verarbeitung im Main schnell genug sein muss bevor der nächste asynchrone Aufruf kommt. Dafür werkelt eben der Thread ungebremst vor sich hin.
Ich stell mal meine Lösung hier rein. Falls da noch etwas falsch sein sollte wäre ich für Hinweise dankbar. Ansonsten steht es als Muster zur Verfügung.
Im der Main-
Unit:
Delphi-Quellcode:
interface
type
TMainForm = class(TForm)
private
...
public
...
myThread: TmyThread;
buffer: TmyBuffer;
bufsize: integer;
procedure OnBufferSwitch(buffer: tmyBuffer; bufidx: Integer);
end;
implementation
procedure TMainForm.FormCreate(Sender: TObject);
begin
bufsize := ...;
buffer := TmyBuffer.Create(bufsize);
myThread := TmyThread.Create(true); //erst suspended
myThread.Buffer := buffer; //Buffer übergeben
myThread.FOnEvent := OnBufferSwitch; //Zuweisung Ereignisprozedur nun hier im Main
myThread.FreeOnTerminate := true;
myThread.Start;
end;
procedure TMainForm.FormClose(Sender: TObject; var Action: TCloseAction);
begin
myThread.Terminate;
buffer.Free;
end;
procedure TMainForm.OnBufferSwitch(bufidx: Integer);
begin
DoSomething(buffer,bufidx); //Auswertung Datenpuffer
end;
und dann in der Thread-
Unit:
Delphi-Quellcode:
interface
type
TOnBufferSwitch = procedure(bufidx: Integer) of object;
type
TmyThread = class(TThread)
private
fbuffer: tmyBuffer;
foldbufidx: integer;
fbufidx: integer;
FCS: TCriticalSection;
procedure AsyncBufferSwitch;
protected
procedure Execute; override;
public
FOnEvent: TOnBufferSwitch;
property Buffer: tmyBuffer read fbuffer write fbuffer;
property OnEvent: TOnBufferSwitch read FOnEvent write FOnEvent;
constructor Create(suspended:boolean); reintroduce;
destructor Destroy; override;
end;
implementation
constructor TmyThread.Create(suspended:boolean);
begin
inherited Create(suspended);
FCS := TCriticalSection.Create;
end;
destructor TmyThread.Destroy;
begin
FCS.Free;
inherited;
end;
procedure TmyThread.Execute;
var oldbufidx: integer;
begin
FOnEvent := MainForm.OnBufferSwitch; //Zuweisung Ereignisprozedur
while not(Terminated) do
begin
CatchDriverData; //do something
...
FCS.Enter;
try
foldbufidx := fbuffer.writebufidx; //aktueller Puffer
fbuffer.Write(DriverDataArray, count); //inkl. autom. Umschaltung Pufferindex, wenn ein Puffer voll
fbufidx := fbuffer.writebufidx; //neuer Pufferindex, falls umgeschaltet
finally
FCS.Leave;
end;
if bufidx <> oldbufidx then
Queue(AsyncBufferSwitch); // <------ hier nun Queue anstelle von Synchronize
sleep(10);
end;
end;
procedure TmyThread.AsyncBufferSwitch;
begin
if Assigned(FOnEvent) then
FOnEvent((fbufidx+1) and $1);
end;
Er wollte so richtig in Delphi einsteigen. Nun steckt er ganz tief drin ...