private unsafe Task WaitForConnectionCoreAsync(CancellationToken cancellationToken)
{
CheckConnectOperationsServerWithHandle();
if (!IsAsync)
{
throw new InvalidOperationException(SR.InvalidOperation_PipeNotAsync);
}
var completionSource = new ConnectionCompletionSource(this, cancellationToken);
if (!Interop.Kernel32.ConnectNamedPipe(InternalHandle, completionSource.Overlapped))
{
int errorCode = Marshal.GetLastWin32Error();
switch (errorCode)
{
case Interop.Errors.ERROR_IO_PENDING:
break;
// If we are here then the pipe is already connected, or there was an error
// so we should unpin and free the overlapped.
case Interop.Errors.ERROR_PIPE_CONNECTED:
// IOCompletitionCallback will not be called because we completed synchronously.
completionSource.ReleaseResources();
if (State == PipeState.Connected)
{
throw new InvalidOperationException(SR.InvalidOperation_PipeAlreadyConnected);
}
completionSource.SetCompletedSynchronously();
// We return a cached task instead of TaskCompletionSource's Task allowing the GC to collect it.
return Task.CompletedTask;
default:
completionSource.ReleaseResources();
throw Win32Marshal.GetExceptionForWin32Error(errorCode);
}
}
// If we are here then connection is pending.
completionSource.RegisterForCancellation();
return completionSource.Task;
}