Ejemplo n.º 1
0
        private async Task <TResponsePacket> SendAndReceiveAsync <TResponsePacket>(Packet packet, CancellationToken cancellationToken) where TResponsePacket : Packet
        {
            cancellationToken.ThrowIfCancellationRequested();

            ushort identifier = 0;

            if (packet is PacketWithId packetWithId)
            {
                identifier = packetWithId.PacketId;
            }

            var awaiter = _packetDispatcher.AddPacketAwaiter <TResponsePacket>(identifier);

            try
            {
                await SendAsync(packet);

                using (var timeoutCts = new CancellationTokenSource(_options.Timeout))
                    using (var linkedCts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, timeoutCts.Token))
                    {
                        linkedCts.Token.Register(() =>
                        {
                            if (!awaiter.Task.IsCompleted && !awaiter.Task.IsFaulted && !awaiter.Task.IsCanceled)
                            {
                                awaiter.TrySetCanceled();
                            }
                        });

                        try
                        {
                            var result = await awaiter.Task.ConfigureAwait(false);

                            timeoutCts.Cancel(false);
                            return((TResponsePacket)result);
                        }
                        catch (OperationCanceledException exception)
                        {
                            if (timeoutCts.IsCancellationRequested && !cancellationToken.IsCancellationRequested)
                            {
                                throw new MqttTimeoutException(exception);
                            }
                            else
                            {
                                throw;
                            }
                        }
                    }
            }
            catch (Exception ex)
            {
                throw new MqttException(ex.Message, ex);
            }
            finally
            {
                _packetDispatcher.RemovePacketAwaiter <TResponsePacket>(identifier);
            }
        }
Ejemplo n.º 2
0
        private async Task <TPacket> SendAndReceiveAsync <TPacket>(Packet packet, CancellationToken cancellationToken = default) where TPacket : Packet
        {
            cancellationToken.ThrowIfCancellationRequested();

            ushort identifier = 0;

            if (packet is PacketWithId packetWithId)
            {
                identifier = packetWithId.PacketId;
            }

            var awaiter = _packetDispatcher.AddPacketAwaiter <TPacket>(identifier);

            await channel.WriteAndFlushAsync(packet);

            using var timeoutCts = new CancellationTokenSource(Options.Timeout);
            using var linkedCts  = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, timeoutCts.Token);

            linkedCts.Token.Register(() =>
            {
                if (!awaiter.Task.IsCompleted && !awaiter.Task.IsFaulted && !awaiter.Task.IsCanceled)
                {
                    awaiter.TrySetCanceled();
                }
            });

            try
            {
                var result = await awaiter.Task.ConfigureAwait(false);

                timeoutCts.Cancel(false);
                return((TPacket)result);
            }
            catch (OperationCanceledException ex)
            {
                _logger.LogError(ex, ex.Message);
                _packetDispatcher.RemovePacketAwaiter <TPacket>(identifier);

                if (timeoutCts.IsCancellationRequested && !cancellationToken.IsCancellationRequested)
                {
                    throw new MqttTimeoutException(ex);
                }
                else
                {
                    throw;
                }
            }
        }