# Cancel running Task on Dispose and race condition

I'm building a wrapper around NamedPipeServerStream and NamedPipeClientStream. Currently my Connect() method on the Client looks like this:

    public async Task Connect(CancellationToken cancellationToken = default(CancellationToken))
{

await _pipe.ConnectAsync(cts.Token).ConfigureAwait(false);

lock (_lock)
{
if (_pipe.IsConnected)
{
_connectCancellationTokenSource.Dispose();
_connectCancellationTokenSource = null;
Connection.Set();
Connected?.BeginInvoke(this, EventArgs.Empty, x => ((EventHandler)x.AsyncState).EndInvoke(x), Connected);

}
}
}


and my Dispose(bool) like this:

    protected override void Dispose(bool disposing)
{
lock (_lock)
{
_connectCancellationTokenSource?.Cancel();
base.Dispose(disposing);
}
}


with the base.Dispose(bool) looking like this:

    protected virtual void Dispose(bool disposing)
{
if (!disposing) return;

Connection.Reset();
_pipe.Dispose();
Connection.Dispose();

_disposed = true;
}


Basically I can't invoke Dispose(bool) while the connection Task is still running and waiting for it to finish is not an option as it might literally run forever.

My workaround was to create a linked CancellationTokenSource and use its token as the CancellationToken for the Task, allowing me to cancel it myself on Dispose().

I then had a race condition where it was entirely possible that the client would connect and pass the if (_pipe.IsConnected) only to be disposed of immediately after, causing it to throw on BeginRead() (which also uses _pipe), hence the lock on both Connect() and Dispose()

However I'm not entirely sure that my approach is really all that sane, and looking for either some validation or ways I could improve this. I'm also concerned I might be putting a bit too much inside the lock...

• What happens if you remove this ConfigureAwait(false); ? – John Peters Dec 14 '17 at 22:33
• And what if Dispose is called before Connect, pipe would be disposed, yet you call ConnectAsync? – dfhwze Sep 17 '19 at 18:31