mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-14 19:09:16 +02:00
* Allow server to run message queue in a thread
git-svn-id: trunk@33705 -
This commit is contained in:
parent
253589b0b6
commit
365a246c9a
@ -40,6 +40,7 @@
|
|||||||
</Target>
|
</Target>
|
||||||
<SearchPaths>
|
<SearchPaths>
|
||||||
<IncludeFiles Value="$(ProjOutDir)"/>
|
<IncludeFiles Value="$(ProjOutDir)"/>
|
||||||
|
<OtherUnitFiles Value="../units/$(TargetCPU)-$(TargetOS)"/>
|
||||||
<UnitOutputDirectory Value="lib/$(TargetCPU)-$(TargetOS)"/>
|
<UnitOutputDirectory Value="lib/$(TargetCPU)-$(TargetOS)"/>
|
||||||
</SearchPaths>
|
</SearchPaths>
|
||||||
</CompilerOptions>
|
</CompilerOptions>
|
||||||
|
@ -6,6 +6,7 @@ uses sysutils,simpleipc;
|
|||||||
|
|
||||||
Var
|
Var
|
||||||
I,Count : Integer;
|
I,Count : Integer;
|
||||||
|
DoStop : Boolean;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
Count:=1;
|
Count:=1;
|
||||||
@ -13,11 +14,19 @@ begin
|
|||||||
try
|
try
|
||||||
ServerID:='ipcserver';
|
ServerID:='ipcserver';
|
||||||
If (ParamCount>0) then
|
If (ParamCount>0) then
|
||||||
ServerInstance:=Paramstr(1);
|
begin
|
||||||
if ParamCount>1 then
|
DoStop:=(ParamStr(1)='-s') or (paramstr(1)='--stop');
|
||||||
Count:=StrToIntDef(ParamStr(2),1);
|
if DoStop then
|
||||||
|
ServerInstance:=Paramstr(2)
|
||||||
|
else
|
||||||
|
ServerInstance:=Paramstr(1);
|
||||||
|
if (Not DoStop) and (ParamCount>1) then
|
||||||
|
Count:=StrToIntDef(ParamStr(2),1);
|
||||||
|
end;
|
||||||
Active:=True;
|
Active:=True;
|
||||||
for I:=1 to Count do
|
if DoStop then
|
||||||
|
SendStringMessage('stop')
|
||||||
|
else for I:=1 to Count do
|
||||||
SendStringMessage(Format('Testmessage %d from client',[i]));
|
SendStringMessage(Format('Testmessage %d from client',[i]));
|
||||||
Active:=False;
|
Active:=False;
|
||||||
finally
|
finally
|
||||||
|
@ -6,7 +6,6 @@
|
|||||||
<Flags>
|
<Flags>
|
||||||
<MainUnitHasCreateFormStatements Value="False"/>
|
<MainUnitHasCreateFormStatements Value="False"/>
|
||||||
<MainUnitHasTitleStatement Value="False"/>
|
<MainUnitHasTitleStatement Value="False"/>
|
||||||
<UseDefaultCompilerOptions Value="True"/>
|
|
||||||
</Flags>
|
</Flags>
|
||||||
<SessionStorage Value="InProjectDir"/>
|
<SessionStorage Value="InProjectDir"/>
|
||||||
<MainUnit Value="0"/>
|
<MainUnit Value="0"/>
|
||||||
@ -29,6 +28,7 @@
|
|||||||
<RunParams>
|
<RunParams>
|
||||||
<local>
|
<local>
|
||||||
<FormatVersion Value="1"/>
|
<FormatVersion Value="1"/>
|
||||||
|
<CommandLineParams Value="-t"/>
|
||||||
</local>
|
</local>
|
||||||
</RunParams>
|
</RunParams>
|
||||||
<Units Count="1">
|
<Units Count="1">
|
||||||
@ -44,6 +44,8 @@
|
|||||||
<Filename Value="ipcserver"/>
|
<Filename Value="ipcserver"/>
|
||||||
</Target>
|
</Target>
|
||||||
<SearchPaths>
|
<SearchPaths>
|
||||||
|
<IncludeFiles Value="$(ProjOutDir)"/>
|
||||||
|
<OtherUnitFiles Value="../units/$(TargetCPU)-$(TargetOS)"/>
|
||||||
<UnitOutputDirectory Value="lib/$(TargetCPU)-$(TargetOS)"/>
|
<UnitOutputDirectory Value="lib/$(TargetCPU)-$(TargetOS)"/>
|
||||||
</SearchPaths>
|
</SearchPaths>
|
||||||
</CompilerOptions>
|
</CompilerOptions>
|
||||||
|
@ -5,31 +5,79 @@ program ipcserver;
|
|||||||
{$APPTYPE CONSOLE}
|
{$APPTYPE CONSOLE}
|
||||||
|
|
||||||
uses
|
uses
|
||||||
|
{$ifdef unix}cthreads,{$endif}
|
||||||
SysUtils,
|
SysUtils,
|
||||||
|
Classes,
|
||||||
simpleipc;
|
simpleipc;
|
||||||
|
|
||||||
|
Type
|
||||||
|
TApp = Class(TObject)
|
||||||
|
Srv : TSimpleIPCServer;
|
||||||
|
DoStop : Boolean;
|
||||||
|
Procedure MessageQueued(Sender : TObject);
|
||||||
|
procedure Run;
|
||||||
|
Procedure PrintMessage;
|
||||||
|
end;
|
||||||
|
|
||||||
|
Procedure TApp.PrintMessage;
|
||||||
|
|
||||||
Var
|
Var
|
||||||
Srv : TSimpleIPCServer;
|
|
||||||
S : String;
|
S : String;
|
||||||
|
|
||||||
|
begin
|
||||||
|
S:=Srv.StringMessage;
|
||||||
|
Writeln('Received message : ',S);
|
||||||
|
DoStop:=DoStop or (S='stop');
|
||||||
|
end;
|
||||||
|
|
||||||
|
Procedure TApp.MessageQueued(Sender : TObject);
|
||||||
|
|
||||||
|
begin
|
||||||
|
Srv.ReadMessage;
|
||||||
|
PrintMessage;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
Procedure TApp.Run;
|
||||||
|
|
||||||
|
Var
|
||||||
|
S : String;
|
||||||
|
Threaded : Boolean;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
Srv:=TSimpleIPCServer.Create(Nil);
|
Srv:=TSimpleIPCServer.Create(Nil);
|
||||||
Try
|
Try
|
||||||
|
S:= ParamStr(1);
|
||||||
|
Threaded:=(S='-t') or (S='--threaded');
|
||||||
Srv.ServerID:='ipcserver';
|
Srv.ServerID:='ipcserver';
|
||||||
Srv.Global:=True;
|
Srv.Global:=True;
|
||||||
Srv.StartServer;
|
if Threaded then
|
||||||
Writeln('Server started. Listening for messages');
|
Srv.OnMessageQueued:=@MessageQueued;
|
||||||
|
Srv.StartServer(Threaded);
|
||||||
|
|
||||||
|
Writeln('Server started. Listening for messages. Send "stop" message to stop server.');
|
||||||
Repeat
|
Repeat
|
||||||
If Srv.PeekMessage(1,True) then
|
If Threaded then
|
||||||
begin
|
begin
|
||||||
S:=Srv.StringMessage;
|
Sleep(10);
|
||||||
Writeln('Received message : ',S);
|
CheckSynchronize;
|
||||||
end
|
end
|
||||||
|
else if Srv.PeekMessage(10,True) then
|
||||||
|
PrintMessage
|
||||||
else
|
else
|
||||||
Sleep(10);
|
Sleep(10);
|
||||||
Until CompareText(S,'stop')=0;
|
Until DoStop;
|
||||||
Finally
|
Finally
|
||||||
Srv.Free;
|
Srv.Free;
|
||||||
end;
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
begin
|
||||||
|
With TApp.Create do
|
||||||
|
try
|
||||||
|
Run
|
||||||
|
finally
|
||||||
|
Free;
|
||||||
|
end;
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
@ -24,7 +24,8 @@ uses
|
|||||||
|
|
||||||
Const
|
Const
|
||||||
MsgVersion = 1;
|
MsgVersion = 1;
|
||||||
|
DefaultThreadTimeOut = 50;
|
||||||
|
|
||||||
//Message types
|
//Message types
|
||||||
mtUnknown = 0;
|
mtUnknown = 0;
|
||||||
mtString = 1;
|
mtString = 1;
|
||||||
@ -33,7 +34,6 @@ type
|
|||||||
TIPCMessageOverflowAction = (ipcmoaNone, ipcmoaDiscardOld, ipcmoaDiscardNew, ipcmoaError);
|
TIPCMessageOverflowAction = (ipcmoaNone, ipcmoaDiscardOld, ipcmoaDiscardNew, ipcmoaError);
|
||||||
|
|
||||||
var
|
var
|
||||||
// Currently implemented only for Windows platform!
|
|
||||||
DefaultIPCMessageOverflowAction: TIPCMessageOverflowAction = ipcmoaNone;
|
DefaultIPCMessageOverflowAction: TIPCMessageOverflowAction = ipcmoaNone;
|
||||||
DefaultIPCMessageQueueLimit: Integer = 0;
|
DefaultIPCMessageQueueLimit: Integer = 0;
|
||||||
|
|
||||||
@ -125,32 +125,46 @@ Type
|
|||||||
|
|
||||||
{ TSimpleIPCServer }
|
{ TSimpleIPCServer }
|
||||||
|
|
||||||
|
TMessageQueueEvent = Procedure(Sender : TObject; Msg : TIPCServerMsg) of object;
|
||||||
|
|
||||||
TSimpleIPCServer = Class(TSimpleIPC)
|
TSimpleIPCServer = Class(TSimpleIPC)
|
||||||
protected
|
protected
|
||||||
Private
|
Private
|
||||||
|
FOnMessageError: TMessageQueueEvent;
|
||||||
|
FOnMessageQueued: TNotifyEvent;
|
||||||
FQueue : TIPCServerMsgQueue;
|
FQueue : TIPCServerMsgQueue;
|
||||||
FGlobal: Boolean;
|
FGlobal: Boolean;
|
||||||
FOnMessage: TNotifyEvent;
|
FOnMessage: TNotifyEvent;
|
||||||
FMsgType: TMessageType;
|
FMsgType: TMessageType;
|
||||||
FMsgData : TStream;
|
FMsgData : TStream;
|
||||||
|
FThreadTimeOut: Integer;
|
||||||
|
FThread : TThread;
|
||||||
|
FLock : TRTLCriticalSection;
|
||||||
|
FErrMsg : TIPCServerMsg;
|
||||||
|
procedure DoMessageQueued;
|
||||||
|
procedure DoMessageError;
|
||||||
function GetInstanceID: String;
|
function GetInstanceID: String;
|
||||||
function GetMaxAction: TIPCMessageOverflowAction;
|
function GetMaxAction: TIPCMessageOverflowAction;
|
||||||
|
function GetMaxQueue: Integer;
|
||||||
function GetStringMessage: String;
|
function GetStringMessage: String;
|
||||||
procedure SetGlobal(const AValue: Boolean);
|
procedure SetGlobal(const AValue: Boolean);
|
||||||
procedure SetMaxAction(AValue: TIPCMessageOverflowAction);
|
procedure SetMaxAction(AValue: TIPCMessageOverflowAction);
|
||||||
|
procedure SetMaxQueue(AValue: Integer);
|
||||||
Protected
|
Protected
|
||||||
FIPCComm: TIPCServerComm;
|
FIPCComm: TIPCServerComm;
|
||||||
|
procedure StartThread; virtual;
|
||||||
|
procedure StopThread; virtual;
|
||||||
Function CommClass : TIPCServerCommClass; virtual;
|
Function CommClass : TIPCServerCommClass; virtual;
|
||||||
Procedure PushMessage(Msg : TIPCServerMsg); virtual;
|
Procedure PushMessage(Msg : TIPCServerMsg); virtual;
|
||||||
function PopMessage: Boolean; virtual;
|
function PopMessage: Boolean; virtual;
|
||||||
Procedure Activate; override;
|
Procedure Activate; override;
|
||||||
Procedure Deactivate; override;
|
Procedure Deactivate; override;
|
||||||
Property Queue : TIPCServerMsgQueue Read FQueue;
|
Property Queue : TIPCServerMsgQueue Read FQueue;
|
||||||
|
Property Thread : TThread Read FThread;
|
||||||
Public
|
Public
|
||||||
Constructor Create(AOwner : TComponent); override;
|
Constructor Create(AOwner : TComponent); override;
|
||||||
Destructor Destroy; override;
|
Destructor Destroy; override;
|
||||||
Procedure StartServer;
|
Procedure StartServer(Threaded : Boolean = False);
|
||||||
Procedure StopServer;
|
Procedure StopServer;
|
||||||
Function PeekMessage(TimeOut : Integer; DoReadMessage : Boolean): Boolean;
|
Function PeekMessage(TimeOut : Integer; DoReadMessage : Boolean): Boolean;
|
||||||
Procedure ReadMessage;
|
Procedure ReadMessage;
|
||||||
@ -160,8 +174,17 @@ Type
|
|||||||
Property MsgData : TStream Read FMsgData;
|
Property MsgData : TStream Read FMsgData;
|
||||||
Property InstanceID : String Read GetInstanceID;
|
Property InstanceID : String Read GetInstanceID;
|
||||||
Published
|
Published
|
||||||
|
Property ThreadTimeOut : Integer Read FThreadTimeOut Write FThreadTimeOut;
|
||||||
Property Global : Boolean Read FGlobal Write SetGlobal;
|
Property Global : Boolean Read FGlobal Write SetGlobal;
|
||||||
|
// Called during ReadMessage
|
||||||
Property OnMessage : TNotifyEvent Read FOnMessage Write FOnMessage;
|
Property OnMessage : TNotifyEvent Read FOnMessage Write FOnMessage;
|
||||||
|
// Called when a message is pushed on the queue.
|
||||||
|
Property OnMessageQueued : TNotifyEvent Read FOnMessageQueued Write FOnMessageQueued;
|
||||||
|
// Called when the queue overflows and MaxAction = ipcmoaError.
|
||||||
|
Property OnMessageError : TMessageQueueEvent Read FOnMessageError Write FOnMessageError;
|
||||||
|
// Maximum number of messages to keep in the queue
|
||||||
|
property MaxQueue: Integer read GetMaxQueue write SetMaxQueue;
|
||||||
|
// What to do when the queue overflows
|
||||||
property MaxAction: TIPCMessageOverflowAction read GetMaxAction write SetMaxAction;
|
property MaxAction: TIPCMessageOverflowAction read GetMaxAction write SetMaxAction;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -464,12 +487,13 @@ begin
|
|||||||
FBusy:=False;
|
FBusy:=False;
|
||||||
FMsgData:=TStringStream.Create('');
|
FMsgData:=TStringStream.Create('');
|
||||||
FQueue:=TIPCServerMsgQueue.Create;
|
FQueue:=TIPCServerMsgQueue.Create;
|
||||||
|
FThreadTimeOut:=DefaultThreadTimeOut;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
destructor TSimpleIPCServer.Destroy;
|
destructor TSimpleIPCServer.Destroy;
|
||||||
begin
|
begin
|
||||||
FreeAndNil(FQueue);
|
|
||||||
Active:=False;
|
Active:=False;
|
||||||
|
FreeAndNil(FQueue);
|
||||||
FreeAndNil(FMsgData);
|
FreeAndNil(FMsgData);
|
||||||
inherited Destroy;
|
inherited Destroy;
|
||||||
end;
|
end;
|
||||||
@ -488,6 +512,11 @@ begin
|
|||||||
FQueue.MaxAction:=AValue;
|
FQueue.MaxAction:=AValue;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TSimpleIPCServer.SetMaxQueue(AValue: Integer);
|
||||||
|
begin
|
||||||
|
FQueue.MaxCount:=AValue;
|
||||||
|
end;
|
||||||
|
|
||||||
function TSimpleIPCServer.GetInstanceID: String;
|
function TSimpleIPCServer.GetInstanceID: String;
|
||||||
begin
|
begin
|
||||||
Result:=FIPCComm.InstanceID;
|
Result:=FIPCComm.InstanceID;
|
||||||
@ -498,6 +527,11 @@ begin
|
|||||||
Result:=FQueue.MaxAction;
|
Result:=FQueue.MaxAction;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TSimpleIPCServer.GetMaxQueue: Integer;
|
||||||
|
begin
|
||||||
|
Result:=FQueue.MaxCount;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
function TSimpleIPCServer.GetStringMessage: String;
|
function TSimpleIPCServer.GetStringMessage: String;
|
||||||
begin
|
begin
|
||||||
@ -505,7 +539,7 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
procedure TSimpleIPCServer.StartServer;
|
procedure TSimpleIPCServer.StartServer(Threaded : Boolean = False);
|
||||||
begin
|
begin
|
||||||
if Not Assigned(FIPCComm) then
|
if Not Assigned(FIPCComm) then
|
||||||
begin
|
begin
|
||||||
@ -515,10 +549,62 @@ begin
|
|||||||
FIPCComm.StartServer;
|
FIPCComm.StartServer;
|
||||||
end;
|
end;
|
||||||
FActive:=True;
|
FActive:=True;
|
||||||
|
If Threaded then
|
||||||
|
StartThread;
|
||||||
|
end;
|
||||||
|
|
||||||
|
Type
|
||||||
|
|
||||||
|
{ TServerThread }
|
||||||
|
|
||||||
|
TServerThread = Class(TThread)
|
||||||
|
private
|
||||||
|
FServer: TSimpleIPCServer;
|
||||||
|
FThreadTimeout: Integer;
|
||||||
|
Public
|
||||||
|
Constructor Create(AServer : TSimpleIPCServer; ATimeout : integer);
|
||||||
|
procedure Execute; override;
|
||||||
|
Property Server : TSimpleIPCServer Read FServer;
|
||||||
|
Property ThreadTimeout : Integer Read FThreadTimeout;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TServerThread }
|
||||||
|
|
||||||
|
constructor TServerThread.Create(AServer: TSimpleIPCServer; ATimeout: integer);
|
||||||
|
begin
|
||||||
|
FServer:=AServer;
|
||||||
|
FThreadTimeout:=ATimeOut;
|
||||||
|
Inherited Create(False);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TServerThread.Execute;
|
||||||
|
begin
|
||||||
|
While Not Terminated do
|
||||||
|
FServer.PeekMessage(ThreadTimeout,False);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TSimpleIPCServer.StartThread;
|
||||||
|
|
||||||
|
begin
|
||||||
|
InitCriticalSection(FLock);
|
||||||
|
FThread:=TServerThread.Create(Self,ThreadTimeOut);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TSimpleIPCServer.StopThread;
|
||||||
|
|
||||||
|
begin
|
||||||
|
if Assigned(FThread) then
|
||||||
|
begin
|
||||||
|
FThread.Terminate;
|
||||||
|
FThread.WaitFor;
|
||||||
|
FreeAndNil(FThread);
|
||||||
|
DoneCriticalSection(FLock);
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TSimpleIPCServer.StopServer;
|
procedure TSimpleIPCServer.StopServer;
|
||||||
begin
|
begin
|
||||||
|
StopThread;
|
||||||
If Assigned(FIPCComm) then
|
If Assigned(FIPCComm) then
|
||||||
begin
|
begin
|
||||||
FIPCComm.StopServer;
|
FIPCComm.StopServer;
|
||||||
@ -529,7 +615,7 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
// TimeOut values:
|
// TimeOut values:
|
||||||
// > 0 -- umber of milliseconds to wait
|
// > 0 -- Number of milliseconds to wait
|
||||||
// = 0 -- return immediately
|
// = 0 -- return immediately
|
||||||
// = -1 -- wait infinitely
|
// = -1 -- wait infinitely
|
||||||
// < -1 -- wait infinitely (force to -1)
|
// < -1 -- wait infinitely (force to -1)
|
||||||
@ -557,9 +643,17 @@ function TSimpleIPCServer.PopMessage: Boolean;
|
|||||||
|
|
||||||
var
|
var
|
||||||
MsgItem: TIPCServerMsg;
|
MsgItem: TIPCServerMsg;
|
||||||
|
DoLock : Boolean;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
MsgItem:=FQueue.Pop;
|
DoLock:=Assigned(FThread);
|
||||||
|
if DoLock then
|
||||||
|
EnterCriticalsection(Flock);
|
||||||
|
try
|
||||||
|
MsgItem:=FQueue.Pop;
|
||||||
|
finally
|
||||||
|
LeaveCriticalsection(FLock);
|
||||||
|
end;
|
||||||
Result:=Assigned(MsgItem);
|
Result:=Assigned(MsgItem);
|
||||||
if Result then
|
if Result then
|
||||||
try
|
try
|
||||||
@ -605,6 +699,55 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
procedure TSimpleIPCServer.DoMessageQueued;
|
||||||
|
|
||||||
|
begin
|
||||||
|
if Assigned(FOnMessageQueued) then
|
||||||
|
FOnMessageQueued(Self);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TSimpleIPCServer.DoMessageError;
|
||||||
|
begin
|
||||||
|
try
|
||||||
|
if Assigned(FOnMessageQueued) then
|
||||||
|
FOnMessageError(Self,FErrMsg);
|
||||||
|
finally
|
||||||
|
FreeAndNil(FErrMsg)
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TSimpleIPCServer.PushMessage(Msg: TIPCServerMsg);
|
||||||
|
|
||||||
|
Var
|
||||||
|
DoLock : Boolean;
|
||||||
|
|
||||||
|
begin
|
||||||
|
try
|
||||||
|
DoLock:=Assigned(FThread);
|
||||||
|
If DoLock then
|
||||||
|
EnterCriticalsection(FLock);
|
||||||
|
try
|
||||||
|
Queue.Push(Msg);
|
||||||
|
finally
|
||||||
|
If DoLock then
|
||||||
|
LeaveCriticalsection(FLock);
|
||||||
|
end;
|
||||||
|
if DoLock then
|
||||||
|
TThread.Synchronize(FThread,@DoMessageQueued)
|
||||||
|
else
|
||||||
|
DoMessageQueued;
|
||||||
|
except
|
||||||
|
On E : Exception do
|
||||||
|
FErrMsg:=Msg;
|
||||||
|
end;
|
||||||
|
if Assigned(FErrMsg) then
|
||||||
|
if DoLock then
|
||||||
|
TThread.Synchronize(FThread,@DoMessageError)
|
||||||
|
else
|
||||||
|
DoMessageQueued;
|
||||||
|
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
{ ---------------------------------------------------------------------
|
{ ---------------------------------------------------------------------
|
||||||
|
@ -229,11 +229,6 @@ begin
|
|||||||
Result:=TPipeServerComm;
|
Result:=TPipeServerComm;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TSimpleIPCServer.PushMessage(Msg: TIPCServerMsg);
|
|
||||||
begin
|
|
||||||
Queue.Push(Msg);
|
|
||||||
end;
|
|
||||||
|
|
||||||
function TSimpleIPCClient.CommClass: TIPCClientCommClass;
|
function TSimpleIPCClient.CommClass: TIPCClientCommClass;
|
||||||
begin
|
begin
|
||||||
if (DefaultIPCClientClass<>Nil) then
|
if (DefaultIPCClientClass<>Nil) then
|
||||||
|
Loading…
Reference in New Issue
Block a user