Title: TBaseWorkerThread
Question: Easy to use,interthread marshaling data communication included,Worker-thread "like" TYPE
Answer:
download complete code sample:
http://web.vip.hr/inga.vip/tthreader.zip
type
TBaseWorkerThread=class;
TInterThreadComm=record
tT:TBaseWorkerThread;
BufferLen:cardinal;
Reason:cardinal;
end;
TBaseWorkerThread=class
private
IsActive:longbool;
TId,ThreadH,CThreadH:cardinal;
StackS:cardinal;
CS,gCS:_RTL_CRITICAL_SECTION;
IsW:longbool;
protected
ThreadStartSnyc:cardinal;
procedure ThreadS ();stdcall;
procedure ThreadAPC ();stdcall;
function IsThreadB:longbool;
public
destructor Destroy;
//THREAD EVENTS!
procedure OnCreateThread;virtual;abstract;
procedure DoJob;virtual;abstract;
procedure OnJobDone;virtual;abstract;
procedure OnDestroyThread;virtual;abstract;
procedure OnMainThreadNotify(Reason:cardinal;Buffer:pointer;BufferLength:cardinal);virtual;abstract;
property StackSize:cardinal read StackS write StackS;
property IsThreadBusy:longbool read IsThreadB;
property ThreadHandle:cardinal read ThreadH;
property ThreadId:cardinal read TId;
function StartThread ():longbool;virtual;
function StartWork ():longbool;virtual;
function CallBackMainThread(Reason:cardinal;Buffer:pointer;BufferLength:cardinal):longbool;virtual;
function DestroyWorkerThread:longbool;
procedure EnterSynchronize;
procedure LeaveSynchronize;
end;
procedure Tmr_Proc (Hwnd,uMsg,IdEvent,eTime:cardinal);stdcall;
procedure Usr_Proc (const Param:TInterThreadComm);stdcall;
implementation
{ TBaseWorkerThreader }
function TBaseWorkerThread.CallBackMainThread(Reason:cardinal;Buffer:pointer;BufferLength:cardinal):longbool;
var
X:cardinal;
begin
X:=GlobalAlloc(0,12+BufferLength);
TInterThreadComm(pointer(x)^).tT:=Self;
TInterThreadComm(pointer(x)^).BufferLen :=BufferLength;
TInterThreadComm(pointer(x)^).Reason :=Reason;
if BufferLength0 then Copymemory(pointer(x+12),Buffer,BufferLength);
result:=QueueUserAPC(addr(Usr_Proc),CThreadH,X);
end;
destructor TBaseWorkerThread.Destroy;
begin
DestroyWorkerThread;
end;
function TBaseWorkerThread.DestroyWorkerThread: longbool;
begin
result:=false;
if ThreadHandle0 then
begin
TerminateThread(ThreadHandle,0);
DeleteCriticalSection(cS);DeleteCriticalSection(gcS);
OnDestroyThread;
CloseHandle(ThreadHandle);
CloseHandle(cThreadH);
ThreadH:=0;
cThreadH:=0;
TId:=0;
result:=true;
IsW:=false;
end;
end;
function TBaseWorkerThread.IsThreadB: longbool;
begin
EnterCriticalSection(cS);
result:=IsW;
LeaveCriticalSection(cS);
end;
procedure TBaseWorkerThread.EnterSynchronize;
begin
EnterCriticalSection(gCs);
end;
procedure TBaseWorkerThread.LeaveSynchronize;
begin
LeaveCriticalSection(gCs);
end;
function TBaseWorkerThread.StartThread(): longbool;
var
ThreadSA:procedure ()of object;stdcall;
cProcess:cardinal;
begin
result:=false;
if ThreadHandle0 then exit;
ThreadSA:=ThreadS;
ThreadStartSnyc:=CreateEvent(0,false,false,0);
ThreadH:=CreateThread(0,StackS,addr(ThreadSA),self,0,TId);
WaitForSingleObject(ThreadStartSnyc,INFINITE);
CloseHandle(ThreadStartSnyc);
result:=longbool(ThreadHandle);
if result then begin
InitializeCriticalSection(cs);InitializeCriticalSection(gcs);
if cardinal(TlsGetValue(200))=0 then TlsSetValue(200,pointer(SetTimer(0,GetCurrentThreadId,0,addr(Tmr_Proc))));
cProcess:=OpenProcess(PROCESS_ALL_ACCESS,true,GetCurrentProcessId);
DuplicateHandle (cProcess,GetCurrentThread, cProcess,addr(CThreadH), $1F03FF, true, 0);
CloseHandle(cProcess);
end;
end;
function TBaseWorkerThread.StartWork: longbool;
var
ThreadSA:procedure ()of object;stdcall;
begin
result:=false;
if ThreadH=0 then exit;
ThreadSA:=ThreadAPC;
result:=QueueUserAPC(addr(ThreadSA),ThreadH,cardinal(self));
end;
procedure TBaseWorkerThread.ThreadAPC;
begin
EnterCriticalSection(cS);
IsW:=true;
LeaveCriticalSection(cS);
DoJob;
end;
procedure TBaseWorkerThread.ThreadS();
begin
SetEvent(ThreadStartSnyc);
OnCreateThread;
while TRUE do begin
SleepEx(INFINITE,true);
EnterCriticalSection(cS);
IsW:=false;
LeaveCriticalSection(cS);
OnJobDone;
end;
end;
procedure Tmr_Proc (Hwnd,uMsg,IdEvent,eTime:cardinal);
begin
SleepEx(0,true);
end;
procedure Usr_Proc (const Param:TInterThreadComm);stdcall;
begin
Param.tT.OnMainThreadNotify(Param.Reason,pointer(cardinal(addr(Param))+12),Param.BufferLen);
GlobalFree(cardinal(addr(Param)));
end;