In this particular case, I’m writing a TCP/IP server, and I’m using TcpListener.BeginAcceptTcpClient() to accept incoming connections. The server logics is implemented in a single class implementing the IDisposable interface: when Dispose() is called, I want to cancel the BeginAcceptTcpClient() operation.
Now in more general terms: when using the async I/O model of .NET (Begin* and End*), how can I cancel the operations?
My idea would be something like this:
private volatile bool canceledFlag = false;
this.listener.BeginAcceptTcpClient(asyncResult =>
{
if(this.canceledFlag) return;
// ...
}, null);
Dispose() would set the flag to true and would also call this.listener.Stop().
However I recall having read that for every Begin* call there must be a matching End* call or bad things would happen.
So how should I do this then? Please note that I’m looking for a general solution for cancellation with Begin* and End* methods – I just gave you my concrete usage scenario to help you understand my question.
The general solution is to call Close() or Dispose() on whatever object whose BeginXxxx() method you called. That will cause the callback to run, when you call EndXxxx() then you’ll get an ObjectDisposedException. Which you should catch and treat as a ‘end of use’ signal, clean up and exit the callback right away. While frowned upon, the use of an exception for flow control is unavoidable.
For TcpListener, use Server.Dispose(), a bit more efficient than calling Stop().