Extracting code from TWebAction for Synchronize()ing in main thread?

216 views Asked by At

I'm having a hard time wrapping my head around using Synchronize from a TWebActionItem.

My webservice is a visual program with form TFormWebServices

var FormWebServices: TFormWebServices;

This has a property FWebBrokerBridge: TIdHTTPWebBrokerBridge
The FWebBrokerBridge registers TWebModuleWebServices as the classes to use for each incoming call:

FWebBrokerBridge.RegisterWebModuleClass(TWebModuleWebServices);

The TWebActionItem items in this class do the work reading a TWebRequest and writing a TWebResponse.

There is one handler that needs to use some VCL visual rendering (shared code with another app) and I want to Synchronize this with the main thread (FormWebServices).

Stub:

TWebModuleWebServices = class(TWebModule)
  procedure WebModuleWebServicesTTGetDynReportAction(Sender: TObject; Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
  procedure WebModuleAfterDispatch(Sender: TObject; Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
 private
   FResponse: TResBase;     // JSON response object
 end;   

procedure TWebModuleWebServices.WebModuleWebServicesTTGetDynReportAction(Sender: TObject; Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
var
  lFrmDynRapport : TFormDynRapport;   // A form containing the common code, has VCL components
begin
  lResponse := (FResponse as TResGetDynReport);  // TResGetDynReport = class(TResBase)
  // ...  
  lFrmDynRapport := TFormDynRapport.Create(Self);
  try
     with lFrmDynRapport do
     begin
        // Do visual stuff with grids, read grid settings, fill lResponse with info specific for this webaction
     end
  finally
  end   
  // ...
end;  

procedure TWebModuleWebServices.WebModuleAfterDispatch(Sender: TObject; Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
var lJSO: ISuperObject;  // SuperObject library
begin
  lJSO := FResponse.ToJson;
  // ...
  Response.Content := lJSO.AsString;
  Handled := true;
end;

Now how can I properly Synchronize the try/finally block? I can get at the current thread and do something simple like:

lThread := TThread.CurrentThread;
TThread.Synchronize(lThread,procedure
  begin
    FormWebServices.MmoLog.Lines.Add('Synchronize test');
  end);

but for anything more complex I'm stuck.
Defining local procedures and feeding these into Synchronize does not work (E2555 cannot capture symbol).
How can I extract the try/finally block so that I can properly execute it in the context of FormWebServices?

1

There are 1 answers

0
Jan Doggen On BEST ANSWER

The trick is to put the entire block in an anonymous method (thanks for the tip, David):

if lFlexRapDM.DesignerCustomOpenDoc(lFlexRapDM.TimeTellReport) then
   begin
      .....
      lThread := TThread.CurrentThread;
      TThread.Synchronize(lThread,procedure
            var l,lIndex       : integer;
            ...
            begin
               lFrmDynRapport := TFormDynRapport.Create(Self);
               try
                  with lFrmDynRapport do
                  begin
                     ...
                  end; // with FrmDynReport
               finally
                  lFrmDynRapport.Free;
               end;
            end); 
      ...         
   end // if lFlexRapDM.DesignerCustomOpenDoc