在第二次使用任何 Async api 调用后,Pi 上的 Bot 崩溃

Posted

技术标签:

【中文标题】在第二次使用任何 Async api 调用后,Pi 上的 Bot 崩溃【英文标题】:Bot on Pi crashes after using any Async api calls a second time 【发布时间】:2018-02-25 22:00:13 【问题描述】:

我将我的 Discord 机器人放在了 Rasberry Pi 上,但现在我遇到了问题。当我尝试使用命令时,它第一次起作用。但是第二次使用它时,它只是说“A MessageReceived 处理程序正在阻止网关任务。”而不是工作。不久之后它会说

System.Exception:服务器错过了最后一个心跳 在 System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () [0x0000c] 在:0 在 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Threading.Tasks.Task 任务) [0x0003e] in :0 在 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Threading.Tasks.Task 任务) [0x00028] in :0 在 System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd (System.Threading.Tasks.Task 任务) [0x00008] in :0 在 System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1+ConfiguredTaskAwaiter[TResult].GetResult () [0x00000] in :0 在 Discord.ConnectionManager+c__DisplayClass28_0+d.MoveNext () [0x0014b] in :0

然后断开连接,尝试重新连接一些但每次都出错。我没有使用命令界面,但我使用的是 async/await。它在我的普通计算机上运行良好,只是在我的 Pi 上中断。

using Discord;
using Discord.WebSocket;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace GlurrrBotDiscord

    public class Program
    
        DiscordSocketClient client;

        static void Main(string[] args) => new Program().MainAsync().GetAwaiter().GetResult();

        public async Task MainAsync()
        
            client = new DiscordSocketClient();

            try
            
                using(StreamReader sr = new StreamReader("botcode.txt"))
                
                    string code = sr.ReadLine();
                    await client.LoginAsync(TokenType.Bot, code);
                
            
            catch(Exception e)
            
                Console.WriteLine("Code not found");
                Console.WriteLine(e.Message);
            

            await client.StartAsync();
            await client.SetGameAsync("praise");

            client.MessageReceived += handleMessage;

            await Task.Delay(-1);
        

        private async Task handleMessage(SocketMessage msg)
        
            Console.WriteLine(msg.Author + " : " + msg.Content);

            if(msg.Content.Contains("/leave"))
            
                var embed = new EmbedBuilder() 
                    Title = msg.Author + " has left",
                    Description = msg.Author + " has left the Discord and would like everyone to know they did. They are very triggered.",
                    Color = Color.DarkRed,
                ;

                await msg.Channel.SendMessageAsync("", false, embed);
            
        
    

完整代码在https://github.com/Silthreent/Glurrr-Discord-Bot

【问题讨论】:

这里发布相关代码。 minimal reproducible example 好吧,任何时候它都使用两个异步调用。 if(msg.Content.Contains("/leave")) var embed = new EmbedBuilder() Title = msg.Author + " has left", Description = msg.Author + " has left the Discord and would like everyone to know they did. They are very triggered.", Color = Color.DarkRed, ; await msg.Channel.SendMessageAsync("", false, embed); 可能是最容易展示的地方。 ~~新的堆栈cmets;看起来像垃圾~~ 您没有将代码放入 cmets,您需要编辑您的问题并将 Minimal Complete Verifiable 示例放在那里。在更新您的问题之前,请阅读 MickyD 发送给您的链接,您在评论中发布的代码不能作为示例。 好的,我更新了主帖,麻烦您了。 与将答案编辑到问题中相反,您应该将其作为答案发布并接受。 【参考方案1】:

Server missed last heartbeat atA MessageReceived handler is blocking the gateway task 的结果,这意味着您正在运行的命令之一使用网关,并使其占用足够长的时间以使连接超时(约 30 秒)。

要解决此问题,您必须实现 a command handler,这是基本机器人实现的一部分。这将允许您异步运行命令,防止线程阻塞。您还可以查看bot sample 以查看上述实现

【讨论】:

无论我等多久,它仍然会在第二个命令上中断。我尝试使用另一个使用命令处理程序的机器人,但它实际上更难破解。它在第一个命令之后中断,执行该命令,然后在不需要第二个命令的情况下给出 MessageRecieved 处理程序问题。 @silthreent 和您是处理程序将其模式设置为异步的用户。并且函数用异步模式属性装饰? 将 runmode 设置为 async 不会给我 MessageRecieved 处理程序消息,但是除了第一个消息之外没有任何消息被发布。 @Silthreent 还确保您将日志级别设置为 LogLevel = LogSeverity.Verbose。或查看我的answer over here 以获取一些登录您的应用程序【参考方案2】:

我通过切换到 DiscordSharpPlus 而不是使用 DiscordNet 来修复它,但实际上仍然不知道问题出在哪里。

【讨论】:

以上是关于在第二次使用任何 Async api 调用后,Pi 上的 Bot 崩溃的主要内容,如果未能解决你的问题,请参考以下文章

AFURLConnectionOperation 在第二次下载开始后停止调用 downloadProgressBlock

为啥我的 ViewController 在第二次调用后才发布,iOS ARC?

RegEx 在第二次破折号出现后匹配任何内容[重复]

Apollo 客户端 writeQuery 更新存储,但 UI 组件仅在第二次函数调用后更新

Vue2事件总线在第二次调用后工作

Vue2事件总线在第二次调用后工作