private Task <CommandResult> SendAsyncInternal <T>(T command, Action <CommandResult> handleResult, TimeSpan timeout, bool setRequestExpiration) where T : class
        {
            var source = new TaskCompletionSource <CommandResult>();

            ServiceBus.BeginPublishRequest(
                command,
                ar =>
            {
                try
                {
                    ServiceBus.EndPublishRequest <T>(ar);
                }
                catch (Exception ex)
                {
                    var result = ex.ToCommandResult();
                    if (handleResult != null)
                    {
                        handleResult(result);
                    }
                    source.SetException(ex);
                }
            },
                null,
                cfg =>
            {
                cfg.UseCurrentSynchronizationContext();
                cfg.Handle <CommandResult>(commandResult =>
                {
                    handleResult(commandResult);
                    source.SetResult(commandResult);
                });
                cfg.HandleFault(fault =>
                {
                    var result = new CommandResult {
                        Success = false, TimeStamp = fault.OccurredAt
                    };
                    foreach (var faultMessage in fault.Messages)
                    {
                        result.Errors.Add(faultMessage);
                    }
                    foreach (var stackTraceItem in fault.StackTrace)
                    {
                        result.ErrorStackTrace.Add(stackTraceItem);
                    }
                    result.ErrorType = fault.FaultType;
                    if (handleResult != null)
                    {
                        handleResult(result);
                    }
                    source.TrySetResult(result);
                });
                cfg.HandleTimeout(timeout, () =>
                {
                    var result = new CommandResult(true, SR.ErrorMsgTaskCancelledDueToTimeout)
                    {
                        ErrorType = typeof(TimeoutException).FullName
                    };
                    if (handleResult != null)
                    {
                        handleResult(result);
                    }
                    source.TrySetCanceled();
                });
                cfg.SetTimeout(timeout);
                if (setRequestExpiration)
                {
                    cfg.SetRequestExpiration(timeout);
                }
            });
            return(source.Task);
        }