Exemple #1
0
        /// <inheritdoc />
        public override async Task WriteAsync(Message message, CancellationToken cancellationToken)
        {
            if (message == null)
            {
                throw new ArgumentNullException(nameof(message));
            }
            if (DisposalToken.IsCancellationRequested)
            {
                throw new ObjectDisposedException(nameof(ByLineTextMessageWriter));
            }
            cancellationToken.ThrowIfCancellationRequested();
            DisposalToken.ThrowIfCancellationRequested();
            using (var linkedTokenSource =
                       CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, DisposalToken))
            {
                var linkedToken = linkedTokenSource.Token;
                var content     = message.ToString();
                await writerSemaphore.WaitAsync(linkedToken);

                try
                {
                    await Writer.WriteLineAsync(content);

                    linkedToken.ThrowIfCancellationRequested();
                    if (Delimiter != null)
                    {
                        await Writer.WriteLineAsync(Delimiter);

                        linkedToken.ThrowIfCancellationRequested();
                    }

                    await Writer.FlushAsync();
                }
                catch (ObjectDisposedException)
                {
                    // Throws OperationCanceledException if the cancellation has already been requested.
                    linkedToken.ThrowIfCancellationRequested();
                    throw;
                }
                finally
                {
                    if (!DisposalToken.IsCancellationRequested)
                    {
                        writerSemaphore.Release();
                    }
                }
            }
        }
        private bool TryTranslateException(Exception exception, CancellationToken cancellationToken1, CancellationToken cancellationToken2)
        {
            // Consumers treat cancellation due their specified token being cancelled differently from cancellation
            // due our instance being disposed. Because we wrap the two in a source, the resulting exception
            // contains it instead of the one that was actually cancelled.
            if (exception is OperationCanceledException)
            {
                cancellationToken1.ThrowIfCancellationRequested();
                cancellationToken2.ThrowIfCancellationRequested();
            }

            if (exception is ObjectDisposedException && DisposalToken.IsCancellationRequested)
            {
                // There's a tiny chance that between checking the cancellation token (wrapping DisposalToken)
                // and checking if the underlying SemaphoreSlim has been disposed, that dispose for this instance
                // (and hence _semaphore) has been run. Handle that and just treat it as a cancellation.
                DisposalToken.ThrowIfCancellationRequested();
            }

            return(false);
        }