/// <summary>高级消费消息。消息处理成功后,自动确认并删除消息体</summary>
        /// <remarks>
        /// Publish 必须跟 ConsumeAsync 配对使用。
        /// </remarks>
        /// <param name="func"></param>
        /// <param name="timeout"></param>
        /// <returns></returns>
        public async Task <TResult> ConsumeAsync <TResult>(Func <T, Task <TResult> > func, Int32 timeout = 0)
        {
#if NET4
            throw new NotSupportedException();
#else
            RetryAck();

            // 取出消息键
            var msgId = (timeout < 0) ?
                        await ExecuteAsync(rc => rc.ExecuteAsync <String>("RPOPLPUSH", Key, AckKey), true) :
                        await ExecuteAsync(rc => rc.ExecuteAsync <String>("BRPOPLPUSH", Key, AckKey, timeout), true);

            // 取出消息。如果重复消费,或者业务层已经删除消息,此时将拿不到
            //var message = Redis.Get<T>(msgId);
            //if (Equals(message, default)) return 0;
            if (!Redis.TryGet(msgId, out T messge))
            {
                // 拿不到消息体,直接确认消息键
                Acknowledge(msgId);
                return(default);