private async Task WriteAsyncCore(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
{
if (NetEventSource.IsEnabled)
{
NetEventSource.Enter(this, WebSocketValidate.GetTraceMsgForParameters(offset, count, cancellationToken));
}
CancellationTokenRegistration cancellationTokenRegistration = new CancellationTokenRegistration();
try
{
if (cancellationToken.CanBeCanceled)
{
cancellationTokenRegistration = cancellationToken.Register(s_OnCancel, this, false);
}
if (!_inOpaqueMode)
{
await _outputStream.WriteAsync(buffer, offset, count, cancellationToken).SuppressContextFlow();
}
else
{
#if DEBUG
// When using fast path only one outstanding read is permitted. By switching into opaque mode
// via IWebSocketStream.SwitchToOpaqueMode (see more detailed comments in interface definition)
// caller takes responsibility for enforcing this constraint.
Debug.Assert(Interlocked.Increment(ref _outstandingOperations._writes) == 1,
"Only one outstanding write allowed at any given time.");
#endif
_writeTaskCompletionSource = new TaskCompletionSource<object>();
_writeEventArgs.BufferList = null;
_writeEventArgs.SetBuffer(buffer, offset, count);
if (WriteAsyncFast(_writeEventArgs))
{
await _writeTaskCompletionSource.Task.SuppressContextFlow();
}
}
}
catch (Exception error)
{
if (s_CanHandleException(error))
{
cancellationToken.ThrowIfCancellationRequested();
}
throw;
}
finally
{
cancellationTokenRegistration.Dispose();
if (NetEventSource.IsEnabled)
{
NetEventSource.Exit(this);
}
}
}