System.Net.WebSockets.ManagedWebSocket.SendFrameLockAcquiredNonCancelableAsync C# (CSharp) Method

SendFrameLockAcquiredNonCancelableAsync() private method

Sends a websocket frame to the network. The caller must hold the sending lock.
private SendFrameLockAcquiredNonCancelableAsync ( MessageOpcode opcode, bool endOfMessage, ArraySegment payloadBuffer ) : Task
opcode MessageOpcode The opcode for the message.
endOfMessage bool The value of the FIN bit for the message.
payloadBuffer ArraySegment The buffer containing the payload data fro the message.
return Task
        private Task SendFrameLockAcquiredNonCancelableAsync(MessageOpcode opcode, bool endOfMessage, ArraySegment<byte> payloadBuffer)
        {
            Debug.Assert(_sendFrameAsyncLock.CurrentCount == 0, "Caller should hold the _sendFrameAsyncLock");

            // If we get here, the cancellation token is not cancelable so we don't have to worry about it,
            // and we own the semaphore, so we don't need to asynchronously wait for it.
            Task writeTask = null;
            bool releaseSemaphore = true;
            try
            {
                // Write the payload synchronously to the buffer, then write that buffer out to the network.
                int sendBytes = WriteFrameToSendBuffer(opcode, endOfMessage, payloadBuffer);
                writeTask = _stream.WriteAsync(_sendBuffer, 0, sendBytes, CancellationToken.None);

                // If the operation happens to complete synchronously (or, more specifically, by
                // the time we get from the previous line to here, release the semaphore, propagate
                // exceptions, and we're done.
                if (writeTask.IsCompleted)
                {
                    writeTask.GetAwaiter().GetResult(); // propagate any exceptions
                    return Task.CompletedTask;
                }

                // Up until this point, if an exception occurred (such as when accessing _stream or when
                // calling GetResult), we want to release the semaphore. After this point, the semaphore needs
                // to remain held until writeTask completes.
                releaseSemaphore = false;
            }
            catch (Exception exc)
            {
                return Task.FromException(_state == WebSocketState.Aborted ?
                    CreateOperationCanceledException(exc) :
                    new WebSocketException(WebSocketError.ConnectionClosedPrematurely, exc));
            }
            finally
            {
                if (releaseSemaphore)
                {
                    _sendFrameAsyncLock.Release();
                }
            }

            // The write was not yet completed.  Create and return a continuation that will
            // release the semaphore and translate any exception that occurred.
            return writeTask.ContinueWith((t, s) =>
            {
                var thisRef = (ManagedWebSocket)s;
                thisRef._sendFrameAsyncLock.Release();

                try { t.GetAwaiter().GetResult(); }
                catch (Exception exc)
                {
                    throw thisRef._state == WebSocketState.Aborted ?
                        CreateOperationCanceledException(exc) :
                        new WebSocketException(WebSocketError.ConnectionClosedPrematurely, exc);
                }
            }, this, CancellationToken.None, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default);
        }