I'm trying to make some work after a response producer.
In order to not hold time responses, I trying do this work in a Thread.
This thread create a DataModule, and do certain stuff (send emails, process file operations, etc) but the execution is blocking the main thread.
I don't use variables or any other interactions with the main thread. I don't see anything that can issuing blocks.
Can anyone help?
Thread code:
unit wdm_Thread;
interface
uses
System.SysUtils, System.Classes, Web.HTTPApp, Web.HTTPProd, Web.DSProd,Data.DB, Data.Win.ADODB;
type
TwdmThread = class(TDataModule)
dbConnection: TADOConnection;
spVisualizador: TADOStoredProc;
spVisualizadorProc: TADOStoredProc;
spVisualizadorProcFim: TADOStoredProc;
spVisualizadorProcInicio: TADOStoredProc;
ppVisualizadorOn: TDataSetPageProducer;
spVisualizadorMiniProc: TADOStoredProc;
end;
colaboreThread = class(TThread)
private
FDataModule: TwdmThread;
FPreviewPath: String;
FSessionID: String;
FUniqueID: String;
FUniqueIDVersao: String;
public
procedure Execute(); override;
class procedure Thumbnail(APreviewPath, ASessionID, AUniqueID, AUniqueIDVersao: String);
end;
implementation
uses
WinAPI.Windows, WinAPI.ActiveX;
{%CLASSGROUP 'System.Classes.TPersistent'}
{$R *.dfm}
{ threadThumbnail }
procedure colaboreThread.Execute;
begin
try
FDataModule := TwdmThread.Create(nil);
with FDataModule do
begin
spVisualizador.Parameters[1].Value := FSessionID;
spVisualizador.Parameters[2].Value := FUniqueID;
spVisualizador.Parameters[3].Value := FUniqueIDVersao;
spVisualizador.Parameters[4].Value := False;
spVisualizador.Open();
if spVisualizador.RecordCount > 0 then
try
DeleteFile(PWideChar(FPreviewPath + FUniqueIDVersao + spVisualizador.FieldByName('Extensao').AsString));
CopyFile(PWideChar(spVisualizador.FieldByName('ArmazenamentoCaminho').AsString + FUniqueIDVersao), PWideChar(FPreviewPath + FUniqueIDVersao + spVisualizador.FieldByName('Extensao').AsString), true);
spVisualizadorMiniProc.Parameters[1].Value := FSessionID;
spVisualizadorMiniProc.Parameters[2].Value := FUniqueID;
spVisualizadorMiniProc.Parameters[3].Value := FUniqueIDVersao;
spVisualizadorMiniProc.Parameters[4].Value := FPreviewPath;
spVisualizadorMiniProc.ExecProc();
finally
DeleteFile(PWideChar(FPreviewPath + FUniqueIDVersao + spVisualizador.FieldByName('Extensao').AsString));
end
end;
finally
FreeAndNil(FDataModule);
end;
end;
class procedure colaboreThread.Thumbnail(APreviewPath, ASessionID, AUniqueID, AUniqueIDVersao: String);
begin
with colaboreThread.Create(True) do
begin
FreeOnTerminate := True;
FPreviewPath := APreviewPath;
FSessionID := ASessionID;
FUniqueID := AUniqueID;
FUniqueIDVersao := FUniqueIDVersao;
if FUniqueIDVersao = '' then FUniqueIDVersao := FUniqueID;
Execute();
end;
end;
initialization
CoInitializeEx(NIL, COINIT_MULTITHREADED or COINIT_SPEED_OVER_MEMORY);
end.
WebModule implementation:
...
procedure TwdmColaboreUP.wdmTopWebUploadwaiUploadAction(Sender: TObject;
Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
begin
colaboreThread.Thumbnail(FPreviewPath, FSessionID, FArquivoUniqueID, FArquivoUniqueIDVersao);
end;
...
You are calling Execute
on the thread, but you should not call it directly. You start the thread using Resume
(or by omitting the Suspended parameter in its constructor). Then, the Execute method will be started in the background.
If you start Execute yourself, like you do now, it is run in the main thread as any other method.
with colaboreThread.Create(True) do
begin
FreeOnTerminate := True;
FPreviewPath := APreviewPath;
FSessionID := ASessionID;
FUniqueID := AUniqueID;
FUniqueIDVersao := FUniqueIDVersao;
if FUniqueIDVersao = '' then FUniqueIDVersao := FUniqueID;
// Execute(); <--- Not this
Resume; // <--- but this
end;