public async Task <bool> Send([NotNull] byte[] data, CancellationToken token = default(CancellationToken))
            {
                if (_state != PipeState.Connected)
                {
                    return(false);
                }
                OverlappingPipeServerStream stream = _stream;

                if (stream == null)
                {
                    return(false);
                }
                await stream.WriteAsync(data, token).ConfigureAwait(false);

                return(true);
            }
            /// <summary>
            /// Starts this instance.
            /// </summary>
            public void Start()
            {
                CancellationTokenSource cts = _cancellationTokenSource;
                if (cts == null)
                    return;

                CancellationToken token = cts.Token;
                _serverTask = Task.Run(
                    async () =>
                    {
                        // The disconnect GUID can be set by a disconnect request if the client requests it.
                        Guid disconnectGuid = Guid.Empty;

                        // Create pipe access rule to allow everyone to connect - may want to change this later
                        try
                        {
                            // Create pipe stream.
                            using (OverlappingPipeServerStream stream = new OverlappingPipeServerStream(
                                _server.Name,
                                _server.MaximumConnections,
                                PipeTransmissionMode.Message,
                                InBufferSize,
                                OutBufferSize,
                                _server._pipeSecurity))
                            {
                                _state = PipeState.Open;

                                // Wait for connection
                                await stream.Connect(token).ConfigureAwait(false);

                                if (!token.IsCancellationRequested)
                                {
                                    // Connect this connection to the service.
                                    _connectionGuid = _server.Service.Connect(this);

                                    if (_connectionGuid != Guid.Empty)
                                    {
                                        ConnectRequest connectRequest = null;

                                        // Set the stream.
                                        _stream = stream;

                                        _server.Add();
                                        _state = PipeState.AwaitingConnect;

                                        try
                                        {
                                            // Keep going as long as we're connected.
                                            while (stream.IsConnected &&
                                                   !token.IsCancellationRequested &&
                                                   _server.Service.State != ServiceControllerStatus.Stopped &&
                                                   _connectionGuid != Guid.Empty)
                                            {
                                                // Read data in.
                                                byte[] data = await stream.ReadAsync(token).ConfigureAwait(false);
                                                if (data == null ||
                                                    token.IsCancellationRequested ||
                                                    _server.Service.State == ServiceControllerStatus.Stopped ||
                                                    _connectionGuid == Guid.Empty)
                                                    break;

                                                // Deserialize the incoming message.
                                                Message message = Message.Deserialize(data);

                                                Request request = message as Request;

                                                // We only accept requests, anything else is a protocol error and so we must disconnect.
                                                if (request == null)
                                                    break;

                                                if (connectRequest == null)
                                                {
                                                    // We require a connect request to start
                                                    connectRequest = request as ConnectRequest;
                                                    if (connectRequest == null)
                                                        break;

                                                    _state = PipeState.Connected;
                                                    _connectionDescription = connectRequest.Description;
                                                    Log.Add(
                                                        LoggingLevel.Notification,
                                                        () => ServiceResources.Not_NamedPipeConnection_Connection,
                                                        _connectionDescription);

                                                    await Send(
                                                        new ConnectResponse(request.ID, _server.Service.ServiceName),
                                                        token)
                                                        .ConfigureAwait(false);
                                                    continue;
                                                }

                                                CommandRequest commandRequest = request as CommandRequest;
                                                if (commandRequest != null)
                                                {
                                                    if (!string.IsNullOrWhiteSpace(commandRequest.CommandLine))
                                                        _commands.TryAdd(
                                                            commandRequest.ID,
                                                            new ConnectedCommand(
                                                                _connectionGuid,
                                                                _server.Service,
                                                                this,
                                                                commandRequest,
                                                                token));
                                                    continue;
                                                }

                                                CommandCancelRequest commandCancelRequest =
                                                    request as CommandCancelRequest;
                                                if (commandCancelRequest != null)
                                                {
                                                    ConnectedCommand cancelled;
                                                    if (_commands.TryRemove(
                                                        commandCancelRequest.CancelCommandId,
                                                        out cancelled))
                                                        // ReSharper disable once PossibleNullReferenceException
                                                        cancelled.Cancel(commandCancelRequest);
                                                    continue;
                                                }

                                                DisconnectRequest disconnectRequest = request as DisconnectRequest;
                                                if (disconnectRequest != null)
                                                {
                                                    // Set the guid for disconnect.
                                                    disconnectGuid = disconnectRequest.ID;
                                                    break;
                                                }
                                            }
                                        }
                                        catch (TaskCanceledException)
                                        {
                                        }

                                        if (stream.IsConnected)
                                            try
                                            {
                                                // Try to send disconnect response.
                                                using (CancellationTokenSource dts = Constants.FireAndForgetTokenSource)
                                                    await Send(
                                                        new DisconnectResponse(disconnectGuid),
                                                        dts.Token)
                                                        .ConfigureAwait(false);
                                            }
                                            catch (TaskCanceledException)
                                            {
                                            }
                                    }
                                }

                                // Remove the stream.
                                _stream = null;
                                _state = PipeState.Closed;
                            }
                        }
                        catch (TaskCanceledException)
                        {
                            // Don't log cancellation.
                        }
                        catch (IOException ioe)
                        {
                            if (!token.IsCancellationRequested)
                                // Common exception caused by sudden disconnect, lower level
                                Log.Add(
                                    ioe,
                                    LoggingLevel.Information,
                                    () => ServiceResources.Err_NamedPipeConnection_Failed);
                        }
                        catch (Exception exception)
                        {
                            if (!token.IsCancellationRequested)
                                Log.Add(
                                    exception,
                                    LoggingLevel.Error,
                                    () => ServiceResources.Err_NamedPipeConnection_Failed);
                        }
                        finally
                        {
                            Dispose();
                        }
                    },
                    token);
            }
            /// <summary>
            /// Starts this instance.
            /// </summary>
            public void Start()
            {
                CancellationTokenSource cts = _cancellationTokenSource;

                if (cts == null)
                {
                    return;
                }

                CancellationToken token = cts.Token;

                _serverTask = Task.Run(
                    async() =>
                {
                    // The disconnect GUID can be set by a disconnect request if the client requests it.
                    Guid disconnectGuid = Guid.Empty;

                    // Create pipe access rule to allow everyone to connect - may want to change this later
                    try
                    {
                        // Create pipe stream.
                        using (OverlappingPipeServerStream stream = new OverlappingPipeServerStream(
                                   _server.Name,
                                   _server.MaximumConnections,
                                   PipeTransmissionMode.Message,
                                   InBufferSize,
                                   OutBufferSize,
                                   _server._pipeSecurity))
                        {
                            _state = PipeState.Open;

                            // Wait for connection
                            await stream.Connect(token).ConfigureAwait(false);

                            if (!token.IsCancellationRequested)
                            {
                                // Connect this connection to the service.
                                _connectionGuid = _server.Service.Connect(this);

                                if (_connectionGuid != Guid.Empty)
                                {
                                    ConnectRequest connectRequest = null;

                                    // Set the stream.
                                    _stream = stream;

                                    _server.Add();
                                    _state = PipeState.AwaitingConnect;

                                    try
                                    {
                                        // Keep going as long as we're connected.
                                        while (stream.IsConnected &&
                                               !token.IsCancellationRequested &&
                                               _server.Service.State != ServiceControllerStatus.Stopped &&
                                               _connectionGuid != Guid.Empty)
                                        {
                                            // Read data in.
                                            byte[] data = await stream.ReadAsync(token).ConfigureAwait(false);
                                            if (data == null ||
                                                token.IsCancellationRequested ||
                                                _server.Service.State == ServiceControllerStatus.Stopped ||
                                                _connectionGuid == Guid.Empty)
                                            {
                                                break;
                                            }

                                            // Deserialize the incoming message.
                                            Message message = Message.Deserialize(data);

                                            Request request = message as Request;

                                            // We only accept requests, anything else is a protocol error and so we must disconnect.
                                            if (request == null)
                                            {
                                                break;
                                            }

                                            if (connectRequest == null)
                                            {
                                                // We require a connect request to start
                                                connectRequest = request as ConnectRequest;
                                                if (connectRequest == null)
                                                {
                                                    break;
                                                }

                                                _state = PipeState.Connected;
                                                _connectionDescription = connectRequest.Description;
                                                Log.Add(
                                                    LoggingLevel.Notification,
                                                    () => ServiceResources.Not_NamedPipeConnection_Connection,
                                                    _connectionDescription);

                                                await Send(
                                                    new ConnectResponse(request.ID, _server.Service.ServiceName),
                                                    token)
                                                .ConfigureAwait(false);
                                                continue;
                                            }

                                            CommandRequest commandRequest = request as CommandRequest;
                                            if (commandRequest != null)
                                            {
                                                if (!string.IsNullOrWhiteSpace(commandRequest.CommandLine))
                                                {
                                                    _commands.TryAdd(
                                                        commandRequest.ID,
                                                        new ConnectedCommand(
                                                            _connectionGuid,
                                                            _server.Service,
                                                            this,
                                                            commandRequest,
                                                            token));
                                                }
                                                continue;
                                            }

                                            CommandCancelRequest commandCancelRequest =
                                                request as CommandCancelRequest;
                                            if (commandCancelRequest != null)
                                            {
                                                ConnectedCommand cancelled;
                                                if (_commands.TryRemove(
                                                        commandCancelRequest.CancelCommandId,
                                                        out cancelled))
                                                {
                                                    // ReSharper disable once PossibleNullReferenceException
                                                    cancelled.Cancel(commandCancelRequest);
                                                }
                                                continue;
                                            }

                                            DisconnectRequest disconnectRequest = request as DisconnectRequest;
                                            if (disconnectRequest != null)
                                            {
                                                // Set the guid for disconnect.
                                                disconnectGuid = disconnectRequest.ID;
                                                break;
                                            }
                                        }
                                    }
                                    catch (TaskCanceledException)
                                    {
                                    }

                                    if (stream.IsConnected)
                                    {
                                        try
                                        {
                                            // Try to send disconnect response.
                                            using (CancellationTokenSource dts = Constants.FireAndForgetTokenSource)
                                                await Send(
                                                    new DisconnectResponse(disconnectGuid),
                                                    dts.Token)
                                                .ConfigureAwait(false);
                                        }
                                        catch (TaskCanceledException)
                                        {
                                        }
                                    }
                                }
                            }

                            // Remove the stream.
                            _stream = null;
                            _state  = PipeState.Closed;
                        }
                    }
                    catch (TaskCanceledException)
                    {
                        // Don't log cancellation.
                    }
                    catch (IOException ioe)
                    {
                        if (!token.IsCancellationRequested)
                        {
                            // Common exception caused by sudden disconnect, lower level
                            Log.Add(
                                ioe,
                                LoggingLevel.Information,
                                () => ServiceResources.Err_NamedPipeConnection_Failed);
                        }
                    }
                    catch (Exception exception)
                    {
                        if (!token.IsCancellationRequested)
                        {
                            Log.Add(
                                exception,
                                LoggingLevel.Error,
                                () => ServiceResources.Err_NamedPipeConnection_Failed);
                        }
                    }
                    finally
                    {
                        Dispose();
                    }
                },
                    token);
            }