multithreading - Delphi: Create and use socket outside main thread -
multithreading - Delphi: Create and use socket outside main thread -
code below intended read info via socket within thread.
//main method dll function getsocketdata(const ip, port: pchar): pchar; export; cdecl; var thread: tmythread; dataisread: tevent; begin dataisread := tevent.create(nil, true, false, ''); thread:= tmythread.create(dataisread, ip, port); dataisread.waitfor(infinite); result := blockalloc(thread.resultdata); dataisread.free; thread.free; end; tmythreadbase = class(tthread) protected fresultdata: string; public constructor create; property resultdata: string read fresultdata; end; constructor tmythreadbase.create; begin inherited create(false); // suspended fresultdata := ''; freeonterminate := false; end; tmythread = class(tmythreadbase) private fmydata: tmydata; fsocketcom: tsocketcom; //other params protected procedure connect(sender: tobject); procedure execute; override; public constructor create(dataisread: tevent; const ip, port: pchar); destructor destroy; override; end; constructor tmythread.create(const ip, port: pchar); begin inherited create; /init params/ coinitialize(nil); fsocketcom := comcreate(fport, fip); fsocketcom.onconnect := connect;//connect method sends special command port {`clientsckt.socket.sendbuf(b[0], count)`} fsocketcom.reopen; fmydata := tmydata.create(dataisread, fsocketcom);//class used received info interpretation //dataisread event beingness set when info interpreted fsocketcom.setrxfunc(fmydata.ncdata);//set method info interpretation fmydata.initdata(...);//init values needed while info beingness interpreted end; destructor tmythread.destroy; begin couninitialize; inherited; end; procedure tmythread.execute; begin inherited; while not terminated sleep(100); //that place not know wait while onread event fired. end; tsocketcom = class(tcustomcom) private clientsckt: tclientsocket; procedure socketconnect(sender: tobject; socket: tcustomwinsocket); procedure socketread(sender: tobject; socket: tcustomwinsocket); protected procedure setthread; override; public constructor create; destructor destroy; override; function open:boolean; override; function read( buf:pansichar; size:integer; wait:integer = 0 ):integer; override; end; procedure tcustomcom.setrxfunc(onrxdata: trxdataevent); begin ... setthread; ... end; function tsocketcom.open:boolean; var i,j:integer; begin ... clientsckt:=tclientsocket.create(nil); clientsckt.clienttype:=ctblocking; clientsckt.hostandaddress:='127.0.0.0'; clientsckt.port:=1234; clientsckt.onconnect:=socketconnect; clientsckt.open; ... end; function tsocketcom.read(buf:pansichar;size:integer; wait:integer):integer; begin if opened result:=clientsckt.socket.receivebuf(buf^,size); if result<0 result:=0; end; procedure tsocketcom.setthread; begin inherited; clientsckt.onread:=socketread; end;
problem: onread event not fired, though seams needed instances created within thread. connection made , command sent.
this kind of code misuse of thread (and misuse of freeonterminate
property), since calling code blocked waiting thread terminate, there no reason have thread in first place.
with said, default tclientsocket
operates in non-blocking mode, uses window messages internally trigger socket events. thread activates socket needs have message loop thosse socket notifications can received , dispatched correctly. otherwise, have utilize socket in blocking mode instead, martin said.
update:
the updated code have shown plain wrong on multiple levels. threading wrong. tclientsocket
usage wrong. given blocking nature of getsocketdata()
function, there no need utilize threads internally @ (especially since stated getsocketdata()
beingness called in thread, threading overkill), , should not bothering tclientsocket
events @ all, onread
event in particular not called in blocking mode @ (which root of problem!).
you made code much more complicated needs be. utilize more instead:
function getsocketdata(const ip, port: pchar): pchar; export; cdecl; var clientsckt: tclientsocket; //other params begin result := nil; seek /init params/ coinitialize(nil); seek clientsckt := tclientsocket.create(nil); seek clientsckt.clienttype := ctblocking; clientsckt.hostandaddress := ip; clientsckt.port := port; clientsckt.open; seek // send special command port here // read info , interpret here result := blockalloc(...); clientsckt.close; end; clientsckt.free; end; couninitialize; end; except end; end;
multithreading delphi sockets
Comments
Post a Comment