示例#1
0
        public async Task <Command> ProcessCommandAsync(ICommandSenderChannel commandSenderChannel, Command requestCommand, CancellationToken cancellationToken)
        {
            if (commandSenderChannel == null)
            {
                throw new ArgumentNullException(nameof(commandSenderChannel));
            }
            if (requestCommand == null)
            {
                throw new ArgumentNullException(nameof(requestCommand));
            }
            if (requestCommand.Status != CommandStatus.Pending)
            {
                throw new ArgumentException("Invalid command status", nameof(requestCommand));
            }

            if (requestCommand.Method == CommandMethod.Observe)
            {
                throw new ArgumentException("Invalid command method", nameof(requestCommand));
            }

            if (requestCommand.Id.IsNullOrEmpty())
            {
                throw new ArgumentException("Invalid command id", nameof(requestCommand));
            }

#if NETSTANDARD1_1
            // TODO: Without the TaskCreationOptions.RunContinuationsAsynchronously, there may occurs deadlock on command results.
            var tcs = new TaskCompletionSource <Command>();
#else
            var tcs = new TaskCompletionSource <Command>(TaskCreationOptions.RunContinuationsAsynchronously);
#endif

            if (!_pendingCommandsDictionary.TryAdd(requestCommand.Id, tcs))
            {
                throw new InvalidOperationException("Could not register the pending command request. The command id is already in use.");
            }
            try
            {
#if NETSTANDARD1_1
                using (cancellationToken.Register(() => tcs.TrySetCanceled()))
#else
                using (cancellationToken.Register(() => tcs.TrySetCanceled(cancellationToken)))
#endif
                {
                    await commandSenderChannel.SendCommandAsync(requestCommand, cancellationToken).ConfigureAwait(false);

                    var result = await tcs.Task.ConfigureAwait(false);

                    return(result);
                }
            }
            finally
            {
                TaskCompletionSource <Command> removedTcs;
                _pendingCommandsDictionary.TryRemove(requestCommand.Id, out removedTcs);
            }
        }
        public async Task <Command> ProcessCommandAsync(ICommandSenderChannel commandSenderChannel, Command requestCommand, CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();

            if (commandSenderChannel == null)
            {
                throw new ArgumentNullException(nameof(commandSenderChannel));
            }
            if (requestCommand == null)
            {
                throw new ArgumentNullException(nameof(requestCommand));
            }
            if (requestCommand.Status != CommandStatus.Pending)
            {
                throw new ArgumentException("Invalid command status", nameof(requestCommand));
            }

            if (requestCommand.Id.IsNullOrEmpty())
            {
                throw new ArgumentException("Invalid command id", nameof(requestCommand));
            }

            var tcs = new TaskCompletionSource <Command>(TaskCreationOptions.RunContinuationsAsynchronously);

            if (!_pendingCommandsDictionary.TryAdd(requestCommand.Id, tcs))
            {
                throw new InvalidOperationException("Could not register the pending command request. The command id is already in use.");
            }
            try
            {
                using (cancellationToken.Register(() => tcs.TrySetCanceled(cancellationToken)))
                {
                    await commandSenderChannel.SendCommandAsync(requestCommand, cancellationToken).ConfigureAwait(false);

                    var result = await tcs.Task.ConfigureAwait(false);

                    return(result);
                }
            }
            finally
            {
                TaskCompletionSource <Command> removedTcs;
                _pendingCommandsDictionary.TryRemove(requestCommand.Id, out removedTcs);
            }
        }
示例#3
0
 /// <summary>
 /// Sends a command to the remote node.
 /// </summary>
 /// <param name="channel"></param>
 /// <param name="command"></param>
 /// <returns></returns>
 public static Task SendCommandAsync(this ICommandSenderChannel channel, Command command)
 {
     return(channel.SendCommandAsync(command, CancellationToken.None));
 }