private async Task CreateReceiver(CancellationToken processorCancellationToken)
        {
            bool releaseSemaphore = false;

            try
            {
                await _concurrentAcceptSessionsSemaphore.WaitAsync(processorCancellationToken).ConfigureAwait(false);

                // only attempt to release semaphore if WaitAsync is successful,
                // otherwise SemaphoreFullException can occur.
                releaseSemaphore = true;
                _receiver        = await ServiceBusSessionReceiver.CreateSessionReceiverAsync(
                    entityPath : _entityPath,
                    connection : _connection,
                    plugins : _plugins,
                    options : _sessionReceiverOptions,
                    cancellationToken : processorCancellationToken).ConfigureAwait(false);
            }
            catch (OperationCanceledException)
            {
                // propagate as TCE so it will be handled by the outer catch block
                throw new TaskCanceledException();
            }
            finally
            {
                if (releaseSemaphore)
                {
                    _concurrentAcceptSessionsSemaphore.Release();
                }
            }
        }
        /// <summary>
        /// Creates a <see cref="ServiceBusSessionReceiver"/> instance that can be used for receiving
        /// and settling messages from a specific session-enabled queue. It uses <see cref="ReceiveMode"/> to specify
        /// how messages are received. Defaults to PeekLock mode. The <see cref="ReceiveMode"/> is set in <see cref="ServiceBusReceiverOptions"/>.
        /// </summary>
        ///
        /// <param name="queueName">The session-enabled queue to create a <see cref="ServiceBusSessionReceiver"/> for.</param>
        /// <param name="options">The set of <see cref="ServiceBusReceiverOptions"/> to use for configuring the
        /// <see cref="ServiceBusSessionReceiver"/>.</param>
        /// <param name="cancellationToken">An optional <see cref="CancellationToken"/> instance to signal the request to cancel the operation.</param>
        ///
        /// <remarks>Because this is establishing a session lock, this method performs a service call. If the
        /// sessionId parameter is not specified, and there are no available messages in the queue, this will
        /// throw a <see cref="ServiceBusException"/> with <see cref="ServiceBusException.Reason"/> of <see cref="ServiceBusException.FailureReason.ServiceTimeout"/>.
        /// </remarks>
        ///
        /// <returns>A <see cref="ServiceBusSessionReceiver"/> scoped to the specified queue and a specific session.</returns>
        public virtual async Task <ServiceBusSessionReceiver> CreateSessionReceiverAsync(
            string queueName,
            ServiceBusSessionReceiverOptions options = default,
            CancellationToken cancellationToken      = default)
        {
            ValidateEntityName(queueName);

            return(await ServiceBusSessionReceiver.CreateSessionReceiverAsync(
                       entityPath : queueName,
                       connection : Connection,
                       options : options,
                       cancellationToken : cancellationToken).ConfigureAwait(false));
        }
        /// <summary>
        /// Creates a <see cref="ServiceBusSessionReceiver"/> instance that can be used for receiving
        /// and settling messages from a specific session-enabled subscription. It uses <see cref="ReceiveMode"/> to specify
        /// how messages are received. Defaults to PeekLock mode. The <see cref="ReceiveMode"/> is set in <see cref="ServiceBusReceiverOptions"/>.
        /// </summary>
        ///
        /// <param name="topicName">The topic to create a <see cref="ServiceBusSessionReceiver"/> for.</param>
        /// <param name="subscriptionName">The session-enabled subscription to create a <see cref="ServiceBusSessionReceiver"/> for.</param>
        /// <param name="options">The set of <see cref="ServiceBusReceiverOptions"/> to use for configuring the
        /// <see cref="ServiceBusSessionReceiver"/>.</param>
        /// <param name="cancellationToken">An optional <see cref="CancellationToken"/> instance to signal the request to cancel the operation.</param>
        ///
        /// <remarks>Because this is establishing a session lock, this method performs a service call. If the
        /// sessionId parameter is not specified, and there are no available messages in the queue, this will
        /// throw a <see cref="ServiceBusException"/> with <see cref="ServiceBusException.Reason"/> of <see cref="ServiceBusException.FailureReason.ServiceTimeout"/>.
        /// </remarks>
        ///
        /// <returns>A <see cref="ServiceBusSessionReceiver"/> scoped to the specified queue and a specific session.</returns>
        public virtual async Task <ServiceBusSessionReceiver> CreateSessionReceiverAsync(
            string topicName,
            string subscriptionName,
            ServiceBusSessionReceiverOptions options = default,
            CancellationToken cancellationToken      = default)
        {
            ValidateEntityName(topicName);

            return(await ServiceBusSessionReceiver.CreateSessionReceiverAsync(
                       entityPath : EntityNameFormatter.FormatSubscriptionPath(topicName, subscriptionName),
                       connection : Connection,
                       options : options,
                       cancellationToken : cancellationToken).ConfigureAwait(false));
        }
        /// <summary>
        /// Creates a <see cref="ServiceBusSessionReceiver"/> instance that can be used for receiving
        /// and settling messages from a specific session-enabled queue. It uses <see cref="ReceiveMode"/> to specify
        /// how messages are received. Defaults to PeekLock mode. The <see cref="ReceiveMode"/> is set in <see cref="ServiceBusReceiverOptions"/>.
        /// </summary>
        ///
        /// <param name="queueName">The session-enabled queue to create a <see cref="ServiceBusSessionReceiver"/> for.</param>
        /// <param name="sessionId">Gets or sets a session ID to scope the <see cref="ServiceBusSessionReceiver"/> to.</param>
        /// <param name="options">The set of <see cref="ServiceBusReceiverOptions"/> to use for configuring the
        /// <see cref="ServiceBusSessionReceiver"/>.</param>
        /// <param name="cancellationToken">An optional <see cref="CancellationToken"/> instance to signal the request to cancel the operation.</param>
        ///
        /// <remarks>Because this is establishing a session lock, this method performs a service call. If the
        /// sessionId parameter is null, and there are no available messages in the queue, this will
        /// throw a <see cref="ServiceBusException"/> with <see cref="ServiceBusException.Reason"/> of <see cref="ServiceBusFailureReason.ServiceTimeout"/>.
        /// </remarks>
        ///
        /// <returns>A <see cref="ServiceBusSessionReceiver"/> scoped to the specified queue and a specific session.</returns>
        public virtual async Task <ServiceBusSessionReceiver> AcceptSessionAsync(
            string queueName,
            string sessionId,
            ServiceBusSessionReceiverOptions options = default,
            CancellationToken cancellationToken      = default)
        {
            ValidateEntityName(queueName);
            options ??= new ServiceBusSessionReceiverOptions();
            options.SessionId = sessionId;

            return(await ServiceBusSessionReceiver.CreateSessionReceiverAsync(
                       entityPath : queueName,
                       connection : Connection,
                       plugins : Plugins,
                       options : options,
                       cancellationToken : cancellationToken).ConfigureAwait(false));
        }
        private async Task CreateAndInitializeSessionReceiver(
            CancellationToken cancellationToken)
        {
            _receiver = await ServiceBusSessionReceiver.CreateSessionReceiverAsync(
                entityPath : _entityPath,
                connection : _connection,
                options : _sessionReceiverOptions,
                cancellationToken : cancellationToken).ConfigureAwait(false);

            if (AutoRenewLock)
            {
                _sessionLockRenewalTask = RenewSessionLock(cancellationToken);
            }

            if (_sessionInitHandler != null)
            {
                var args = new ProcessSessionEventArgs(_receiver, cancellationToken);
                await _sessionInitHandler(args).ConfigureAwait(false);
            }
        }