bluestar
asked on
how can I make my remote data module support multiple thread?
in delphi5 I create remote app server using Apartment thread module,
in my remote app server have a simple method 'myfunc',it only delay some time.
in my client application i make a thread object 'TMyThread',it call remote server's 'myfunc'
i want the remote app server's method exec in multiple thread.
for example in my client application,i make three thread T1,T2,T3,T1 delay 1 second,
T2 delay 2 second,T3 delay 3 second,i want total cost is 3 second,but now it is 6 second.
how can i make it total cost 3 second.
following is my client application code.
unit mythread;
interface
uses
Classes, Graphics, ExtCtrls,mconnect,stdctrls ,Sysutils, Db,
DBClient,Windows,sconnect, comobj,Act iveX;
type
TMyThread=class(TThread)
private
Foconnect:TCustomConnectio n;
FsResult:String;
FiSecond:integer;
protected
procedure Execute; override;
procedure dofunc;
public
constructor Create(poconnect:TCustomCo nnection;p iSecond:In teger);
end;
implementation
constructor TMyThread.Create
(poDcom:TCustomConnection; piSecond:I nteger);
begin
Foconnect :=poconnect;
FoMemo:=poMemo;
FiSecond:=piSecond;
freeOnTerminate:=False;
inherited Create(False);
end;
procedure TMyThread.dofunc;
var
sResult:variant;
begin
(Foconnect as TSocketConnection).AppServ er.myfunc( FiSecond,s Result);
FsResult:=sResult+'FiSecon d is'+IntToStr(FiSecond);
end;
procedure TMyThread.Execute;
begin
...
...
Synchronize(dofunc);
...
...
end;
end.
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
Db, DBClient, MConnect, StdCtrls, Spin, ExtCtrls, SConnect;
type
TForm1 = class(TForm)
Button1: TButton;
txt2: TSpinEdit;
Label1: TLabel;
Label2: TLabel;
txt3: TMemo;
SocketConnection1: TSocketConnection;
SocketConnection2: TSocketConnection;
SocketConnection3: TSocketConnection;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
uses mythread;
{$R *.DFM}
var
intseconds:integer;
ThreadRuning:integer;
istart,iend:integer;
idelay:double;
T1,T2,T3:TMyThread;
procedure TForm1.Button1Click(Sender : TObject);
begin
intseconds:=StrToInt(txt2. Text);
SocketConnection1.Connecte d:=True;
SocketConnection2.Connecte d:=True;
SocketConnection3.Connecte d:=True;
ThreadRuning:=3;
T1:=TMyThread.create(Socke tConnectio n1,intseco nds);
T2:=TMyThread.create(Socke tConnectio n2,intseco nds*2);
T3:=TMyThread.create(Socke tConnectio n3,intseco nds*3);
{
I want T1,T2,T3 exec simultaneity,but now it is T1
finish, then T2 run, T2 finish then T3 run
}
end;
end.
in my remote app server have a simple method 'myfunc',it only delay some time.
in my client application i make a thread object 'TMyThread',it call remote server's 'myfunc'
i want the remote app server's method exec in multiple thread.
for example in my client application,i make three thread T1,T2,T3,T1 delay 1 second,
T2 delay 2 second,T3 delay 3 second,i want total cost is 3 second,but now it is 6 second.
how can i make it total cost 3 second.
following is my client application code.
unit mythread;
interface
uses
Classes, Graphics, ExtCtrls,mconnect,stdctrls
DBClient,Windows,sconnect,
type
TMyThread=class(TThread)
private
Foconnect:TCustomConnectio
FsResult:String;
FiSecond:integer;
protected
procedure Execute; override;
procedure dofunc;
public
constructor Create(poconnect:TCustomCo
end;
implementation
constructor TMyThread.Create
(poDcom:TCustomConnection;
begin
Foconnect :=poconnect;
FoMemo:=poMemo;
FiSecond:=piSecond;
freeOnTerminate:=False;
inherited Create(False);
end;
procedure TMyThread.dofunc;
var
sResult:variant;
begin
(Foconnect as TSocketConnection).AppServ
FsResult:=sResult+'FiSecon
end;
procedure TMyThread.Execute;
begin
...
...
Synchronize(dofunc);
...
...
end;
end.
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
Db, DBClient, MConnect, StdCtrls, Spin, ExtCtrls, SConnect;
type
TForm1 = class(TForm)
Button1: TButton;
txt2: TSpinEdit;
Label1: TLabel;
Label2: TLabel;
txt3: TMemo;
SocketConnection1: TSocketConnection;
SocketConnection2: TSocketConnection;
SocketConnection3: TSocketConnection;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
uses mythread;
{$R *.DFM}
var
intseconds:integer;
ThreadRuning:integer;
istart,iend:integer;
idelay:double;
T1,T2,T3:TMyThread;
procedure TForm1.Button1Click(Sender
begin
intseconds:=StrToInt(txt2.
SocketConnection1.Connecte
SocketConnection2.Connecte
SocketConnection3.Connecte
ThreadRuning:=3;
T1:=TMyThread.create(Socke
T2:=TMyThread.create(Socke
T3:=TMyThread.create(Socke
{
I want T1,T2,T3 exec simultaneity,but now it is T1
finish, then T2 run, T2 finish then T3 run
}
end;
end.
ASKER
to Felixin,I am sure i have do this,fllowing is code,but it still can not work like i want it is
initialization
TComponentFactory.Create(C omServer, TAMServer,
Class_AMServer, ciMultiInstance, tmApartment);
initialization
TComponentFactory.Create(C
Class_AMServer, ciMultiInstance, tmApartment);
I think you client code is incorrect.
The fact that dofunc on the client wrap into Synchronize
call and work in main thread in any case.
Try correct you code as following
procedure TMyThread.Execute;
begin
OleCheck(CoInitializeEx(ni l, COINIT_APARTMENTTHREADED)) ;
dofunc; // not Synchronize !!!
...
...
end;
The fact that dofunc on the client wrap into Synchronize
call and work in main thread in any case.
Try correct you code as following
procedure TMyThread.Execute;
begin
OleCheck(CoInitializeEx(ni
dofunc; // not Synchronize !!!
...
...
end;
ASKER
thank SChertkov,but when i call remote app server's method
from thread (not Synchronize ) it always raise exception. i must create TSocketConnection in the thread ? can you show me some sample code how to call remote app server's method in the thread.
from thread (not Synchronize ) it always raise exception. i must create TSocketConnection in the thread ? can you show me some sample code how to call remote app server's method in the thread.
ASKER
thank SChertkov,but when i call remote app server's method
from thread (not Synchronize ) it always raise exception. i must create TSocketConnection in the thread ? can you show me some sample code how to call remote app server's method in the thread.
from thread (not Synchronize ) it always raise exception. i must create TSocketConnection in the thread ? can you show me some sample code how to call remote app server's method in the thread.
That exception raised ?
You shure that initialize OLE in this thread
(OleCheck(CoInitializeEx(n il, COINIT_APARTMENTTHREADED)) ?
You shure that initialize OLE in this thread
(OleCheck(CoInitializeEx(n
I see sconnect.pas more carefully and ascertain that
TSocketConnection can work only in main thread or
may be in thread that have message queue.
You can try create thread with message queue,
but i am not sure that TSocketConnection will be
normal work.
TSocketConnection can work only in main thread or
may be in thread that have message queue.
You can try create thread with message queue,
but i am not sure that TSocketConnection will be
normal work.
For do this, also you must create and use TSocketConnection in TThread.Execute body.
It's work !
Try following code:
const
CM_INIT = WM_USER + 101;
type
TSocketThread = class(TThread)
private
Handle: Cardinal;
SocketConnection: TSocketConnection;
sResult: OleVariant;
procedure WndProc(var Message: TMessage);
protected
procedure Execute; override;
end;
procedure TSocketThread.WndProc(var Message: TMessage);
begin
if Message.Msg = CM_INIT then
begin
SocketConnection.Host := 'localhost';
SocketConnection.Port := 211;
SocketConnection.ServerNam e := 'Project1.abc';
SocketConnection.Connected := True;
sResult := SocketConnection.AppServer .myfunc(10 0);
SocketConnection.Close;
Terminate;
end;
end;
procedure TSocketThread.Execute;
var
msg: TMsg;
begin
OleCheck(CoInitializeEx(ni l, COINIT_APARTMENTTHREADED)) ;
SocketConnection := TSocketConnection.Create(n il);
Handle := AllocateHWnd(WndProc);
try
PostMessage(Handle, CM_INIT, 0, 0);
while GetMessage(msg, 0, 0, 0) and not Terminated do
DispatchMessage(msg);
finally
DeallocateHWnd(Handle);
SocketConnection.Free;
end;
end;
procedure TForm3.Button1Click(Sender : TObject);
var
SocketThread: TSocketThread;
begin
SocketThread := TSocketThread.Create(True) ;
SocketThread.FreeOnTermina te := True;
SocketThread.Resume;
end;
Try following code:
const
CM_INIT = WM_USER + 101;
type
TSocketThread = class(TThread)
private
Handle: Cardinal;
SocketConnection: TSocketConnection;
sResult: OleVariant;
procedure WndProc(var Message: TMessage);
protected
procedure Execute; override;
end;
procedure TSocketThread.WndProc(var Message: TMessage);
begin
if Message.Msg = CM_INIT then
begin
SocketConnection.Host := 'localhost';
SocketConnection.Port := 211;
SocketConnection.ServerNam
SocketConnection.Connected
sResult := SocketConnection.AppServer
SocketConnection.Close;
Terminate;
end;
end;
procedure TSocketThread.Execute;
var
msg: TMsg;
begin
OleCheck(CoInitializeEx(ni
SocketConnection := TSocketConnection.Create(n
Handle := AllocateHWnd(WndProc);
try
PostMessage(Handle, CM_INIT, 0, 0);
while GetMessage(msg, 0, 0, 0) and not Terminated do
DispatchMessage(msg);
finally
DeallocateHWnd(Handle);
SocketConnection.Free;
end;
end;
procedure TForm3.Button1Click(Sender
var
SocketThread: TSocketThread;
begin
SocketThread := TSocketThread.Create(True)
SocketThread.FreeOnTermina
SocketThread.Resume;
end;
ASKER
very thank SChertkov answer my question,but i can not compile you code,error message is undeclared identifier 'AllocateHWnd',undeclared identifier 'DeallocateHWnd'. where the function 'AllocateHWnd' and 'DeallocateHWnd' are declared?please tell me. thank again
unit Forms...
ASKER
thank SChertkov ,you code real work,but i find a new problem OnTerminate event can not be trrige! why?
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
TComponentFactory.Create
with the Instancing Call set to ciMultiInstance.