indy - Delphi, Indy10, How to properly stop and cleanup a readln on a continuous stream -
using delphi 2010 , indy10
i attempting read server sent events delphi. have managed create thread subscribe connection on server (python/flask) , capture events. thread needed because http.get blocking forever. realize entire protocol not implemented, interested in receiving short strings broadcast server. following code works, have not been able figure out how cleanly stop thread , free http_client , stream when stopping program.
on server side ""an existing connection forcibly close remote host"" , program indicating memory leaks. have tried many different combinations of trying close http connection @ various points (onterminate,destroy) , can't work. insights or examples appreciated.
here relevant code have far:
tssethread = class(tthread) private url: string; stream: tmemorystream; http_client: tidhttp; procedure doonwork(asender: tobject; aworkmode: tworkmode; aworkcount: int64); public constructor create(createsuspended: boolean; url: string); procedure execute; override; end; constructor tssethread.create(createsuspended: boolean; url: string); begin inherited create(createsuspended); // sending false here self.freeonterminate := false; self.url := url; end; procedure tssethread.execute; begin inherited; try stream := tmemorystream.create; http_client := tidhttp.create(nil); http_client.onwork := doonwork; http_client.request.cachecontrol := 'no-cache'; http_client.request.accept := 'text/event-stream'; http_client.response.keepalive := true; while not terminated try http_client.get(self.url,stream); except on e: exception begin try http_client.disconnect; except end; if http_client.iohandler <> nil http_client.iohandler.inputbuffer.clear; sleep(3000); end; end; http_client.free; stream.free; end; end; procedure tssethread.doonwork(asender: tobject; aworkmode: tworkmode; aworkcount: int64); var msg: string; begin if self.terminated exit; setstring(msg,pansichar(stream.memory),stream.size); stream.position := 0; if pos('data:',msg) > 0 begin // handle msg here. works fine. end; end;
in onwork event handler, when thread's terminated property true, raise exception (such calling sysutils.abort()) instead of calling exit. exception abort http request , close connection, propegate execute(), catch , check terminated again break while loop , let finally block free tidhttp object before exiting execute() terminate thread.
procedure tssethread.doonwork(asender: tobject; aworkmode: tworkmode; aworkcount: int64); var msg: string; begin //if self.terminated exit; if self.terminated sysutils.abort; ... end;
Comments
Post a Comment