Right now Frame 1 is in a loop (looking for data from Serial Comport) and writes to a string variable A in a separate unit. Frame1 then loops until another boolean variable B is true meaning Frame2 has processed its routine. Frame 2 uses a timer to check for changes in variable A then executes a procedure when the variable has changed and sets boolean variable B to true. Looping in Frame 1 and checking for variable B to become true leads to Frame 2 can't fire it's timer anymore because probably the message queue doesn't become empty anymore.
Right now i can only help myself with sleep(xxx). But i want better performance.
Please help :)
Thank you
Edit1: i forgot to mention the point from the topic header. i want to get rid of the timer and call the procedure in frame2 directly.
Edit2: code:
Frame1:
procedure TFrmSerial.TimerSerialTimer(Sender: TObject);
var
resultserial:string;
sl:Tstringlist;
iloop:integer;
begin
if CheckBox1.Checked then
begin
TimerSerialTimer.Enabled:=false;
readString(resultserial); //reads comport data to string
if (resultserial<>'') then
begin
sl:=TStringList.Create;
sl.Sorted:=true;
sl.Duplicates:=dupIgnore;
try
sl.Text:=resultserial;
unit3.DataProcessed:=true;
repeat
if (unit3.DataProcessed=true) then
begin
edit1.Text:=sl[0];
sl.Delete(0);
unit3.DataProcessed:=false;
end
else if (unit3.DataProcessed=false) then
begin
sleep(800);
unit3.DataProcessed:=true; //ugly workaround
end
else
begin
showmessage('undefined state');
end;
until (sl.Count=0);
finally
sl.Free;
end;
end;
TimerSerialTimer.Enabled:=true;
end;
end;
Frame2: code:
procedure TFrmProcessing.Timer1Timer(Sender: TObject);
begin
if self.Visible then
begin
timer1.enabled:=false;
if ProcessString<>ProcessStringBefore then
begin
ProcessStringBefore:=ProcessString;
if length(ProcessString)>2 then DoWork;
end;
unit3.DataProcessed:=true;
timer1.enabled:=true;
end;
end;
I think your problem can be solved with callbacks. Something like this:
type
...
TMyCallback = procedure of Object;
...
of Object
means that this procedure should be class method.
If you define variable with this type and than assign some procedure with the same attributes you can call it by calling this variable:
type
TMyCallback = procedure of Object;
TForm2 = class(TForm)
private
...
protected
...
public
callback:TMyCallback;
...
end;
...
procedure Form1.DoSomething;
begin
// do something
end;
procedure Form1.DoSomethingWithEvent;
begin
callback := DoSomething; //assign procedure to variable
if assigned(callback)
callback; //call procedure DoSomething
end;
You should do something like this in your case. It's just example because I didn't see all your code, but I'll try to make it workable:
Frame1:
type
TSerialEvent = function(aResult:String):Boolean of Object;
Frame1 = class(TFrame)
private
...
protected
...
public
...
Callback:TSerialEvent;
end;
...
procedure TFrmSerial.TimerSerialTimer(Sender: TObject);
var
resultserial:string;
sl:Tstringlist;
iloop:integer;
begin
if CheckBox1.Checked then
begin
TimerSerialTimer.Enabled:=false;
readString(resultserial); //reads comport data to string
if (resultserial<>'') then
begin
sl:=TStringList.Create;
sl.Sorted:=true;
sl.Duplicates:=dupIgnore;
try
sl.Text:=resultserial;
repeat
edit1.Text := sl[0];
sl.Delete(0);
if assigned(Callback) then
begin
//Let's call Process method of TFrmProcessing:
if not Callback(edit1.text) then //it's not good idea to use edit1.text as proxy, but we have what we have
raise Exception.Create('Serial string was not processed');
end
else
raise Exception.Create('No Callback assigned');
until (sl.Count=0);
finally
sl.Free;
end;
end;
TimerSerialTimer.Enabled:=true;
end;
end;
Frame2: You don't need Timer anymore. Everything will be processed in event:
type
TFrmProcessing = class(TFrame)
private
...
protected
...
public
...
function Process(aResult:String):Boolean;
end;
function TFrmProcessing.Process(aResult:String):Boolean;
begin
result := false;
if self.Visible then
begin
if aResult <> ProcessStringBefore then
begin
ProcessStringBefore := aResult;
if length(ProcessString) > 2 then DoWork;
result := true;
end;
end;
end;
And the last thing: you have to assign method Process
of TFrmProcessing
to Callback
of Frame1
. I think you should do it at Form1.Create
or another method you are using for initialization:
...
procedure Form1.FormCreate(Sender:TObject);
begin
...
Frame1.Callback := FrmProcessing.Process;
...
end;