Ejemplo n.º 1
0
        /// <summary>
        /// Send a message to the client. Cancelling <paramref name="ct"/> during WriteAsync
        /// will result in a lost connection. Thread-safe.
        /// </summary>
        /// <param name="msg"></param>
        /// <param name="ct"></param>
        /// <param name="log"></param>
        /// <returns>True if message sent. False if connection lost.</returns>
        public async Task <bool> WriteAsync(string msg, CancellationToken ct, bool log = false)
        {
            const string funcName = nameof(WriteAsync);

            if (ConnectionStatus == ConnectionStatusEnum.Disconnected)
            {
                return(false);
            }

            if (log)
            {
                Log.DebugEx(funcName, $"[{_logName}] Sending message {msg}", false);
            }

            // Add end chars here
            var msgBytes = Encoding.UTF8.GetBytes(msg + (_implicitEndOfMessageString ? _endOfMessageString : string.Empty));

            await _sendMessageLock.WaitAsync(ct); // Lock

            try
            {
                using (ct.Register(() => _tcpStream.Dispose()))
                {
                    // NetworkStream does not override WriteAsync.
                    // This means that it will get the default behavior
                    // of Stream.WriteAsync which just throws the token away after checking it initially.
                    // Disposing _tcpStream cancels the write operation.
                    //
                    // Throw IOException when write fails.
                    // Throw ObjectDisposedException when stream disposed.
                    await _tcpStream.WriteAsync(msgBytes, 0, msgBytes.Length, ct);

                    return(true);
                }
            }
            catch (Exception e) when(e is ObjectDisposedException || e is IOException)
            {
                _sendMessageFailedSignal.TryRelease();
                ct.ThrowIfCancellationRequested();
                return(false);
            }
            finally
            {
                _sendMessageLock.Release(); // Release
            }
        }