what i'm trying create 'listener' listens several different tcp ports @ once, , pipes messages observers.
pseudo-ish code:
private bool _listen = false; public void start() { _listen = true; task.factory.startnew(() => listen(1); task.factory.startnew(() => listen(2); } public void stop() { _listen = false; } private async void listen(int port) { var tcp = new tcpclient(); while(_listen) { await tcp.connectasync(ip, port); using (/*networkstream, binaryreader, etc*/) { while(_listen) { //read binary reader , onnext iobservable } } } }
(for brevity, i've omitted try/catch inside 2 whiles, both of check flag)
my question is: should locking flag, , if so, how tie-in async/await bits?
first of all, should change return type task, not void. async void
methods fire-and-forget , can't awaited or cancelled. exist allow creation of asynchronous event handlers or event-like code. should never used normal asynchronous operations.
the tpl way cooperatively cancel/abort/stop asynchronous operation use cancellationtoken. can check token's iscancellationrequested property see if need cancel operation , stop.
even better, asynchronous methods provided framework accept cancellationtoken can stop them immediatelly without waiting them return. can use networkstream's readasync(byte[], int32, int32, cancellationtoken) read data , cancel immediatelly when calls stop method.
you change code this:
cancellationtokensource _source; public void start() { _source = new cancellationtokensource(); task.factory.startnew(() => listen(1, _source.token),_source.token); task.factory.startnew(() => listen(2, _source.token), _source.token); } public void stop() { _source.cancel(); } private async task listen(int port,cancellationtoken token) { var tcp = new tcpclient(); while(!token.iscancellationrequested) { await tcp.connectasync(ip, port); using (var stream=tcp.getstream()) { ... try { await stream.readasync(buffer, offset, count, token); } catch (operationcanceledexception ex) { //handle cancellation } ... } } }
you can read lot more cancellation in cancellation in managed threads, including advice on how poll, register callback cancellation, listen multiple tokens etc.
the try/catch
block exists because await
throws exception if task cancelled. can avoid calling continuewith on task returned readasync , checking iscanceled flag:
private async task listen(int port,cancellationtoken token) { var tcp = new tcpclient(); while(!token.iscancellationrequested) { await tcp.connectasync(ip, port); using (var stream=tcp.getstream()) { ///... await stream.readasync(buffer, offset, count, token) .continuewith(t => { if (t.iscanceled) { //do cleanup? } else { //process buffer , send notifications } }); ///... } } }
await
awaits simple task
finishes when continuation finishes