DZ-Jay wrote:
> On Oct 11, 2007, at 06:47, Arno Garrels wrote:
>
>> Iterating thru Srv.Clients is not the way to go!! It is not
>> thread-save and will most likely throw strange AVs. Instead
>> iterate thru the thread-list and post a custom message to each
>> thread, the inside the thread iterate thru each thread's
>> client list, see TWSocketThrdServer.DisconnectAll as example.
>> Now one problem is that TWSocketThrdServer has no public property
>> ThreadList and TWsClientThread.PumpMessages doesn't fire an event
>> OnMessage. So the code has to be tweaked a little bit for common use.
>
> So, would you recommend that I extend the component and override
> DisconnectAll to, say, fire an event that I could hook on to send the
> messages; and then call DisconnectAll() from my worker thread instead
> of using the loop? If so, we should add something like this to the
> component itself, no? (I could provide the code when I'm done with
> it.)
I suggest an event OnMessage that fires from PumpMessages like this:
TMessageEvent = procedure(Sender: TObject; var Msg: TMessage; var Handled:
Boolean);
TWsClientThread = class(TThread)
private
FReadyForMsgs : Boolean;
FServer : TWSocketThrdServer;
FClients : TList;
FEventArray : array [TWsClientThreadEventID] of THandle;
FOnMessage : TMessageEvent;
protected
procedure DetachClient(Client: TWSocketThrdClient);
procedure AttachClient(Client: TWSocketThrdClient);
procedure DisconnectAll;
procedure PumpMessages(WaitForMessages : Boolean); virtual;
procedure Execute; override;
function GetClientCount : Integer;
public
constructor Create(Suspended : Boolean);
destructor Destroy; override;
property ClientCount : Integer read GetClientCount;
property ReadyForMsgs : Boolean read FReadyForMsgs;
property OnMessage : TMessageEvent read FOnMessage
write FOnMessage;
end;
procedure TWsClientThread.PumpMessages(WaitForMessages: Boolean);
..
WM_THREAD_EXCEPTION_TEST :
raise Exception.Create('** TEST EXCEPTION ***')
else
MsgRec.Msg := Msg.message;
MsgRec.WParam := Msg.wParam;
MsgRec.LParam := Msg.lParam;
Handled := False;
if Assigned(FOnMessage) then
FOnMessage(Self, MsgRec, Handled);
if not Handled then
Dispatch(MsgRec);
end;
This is untested code. Also FThreadList has to be made public.
Note that OnMessage would fire in different thread contexts but
a single handler for all is fine. Hope this helps.
>
>> The only reason why I started writing this component was to derive
>> a SSL multi-threaded server from it only to be able to test
>> thread-safety of the SSL code.
>
> Are you suggesting the component is not stable for a production
> application?
I think it isn't very fast, I tested once with some stress
clients and many concurrent connections successfully over many
hours until that point it looked stable. In any case I won't use
multi-threading if not absolutely necessary, simply because it's
easier to code and to debug. TWSocketServer can handle many hundreds
of concurrent connections in a single thread.
--
Arno Garrels [TeamICS]
http://www.overbyte.be/eng/overbyte/teamics.html
--
To unsubscribe or change your settings for TWSocket mailing list
please goto http://www.elists.org/mailman/listinfo/twsocket
Visit our website at http://www.overbyte.be