【问题标题】:Discord bot Task.Delay() does not work parallelDiscord bot Task.Delay() 不能并行工作
【发布时间】:2020-11-18 15:27:41
【问题描述】:

我在创建不和谐机器人时遇到问题,异步对我来说是新事物。问题是这个 Task.Delay() 延迟了整个程序,而不是单个方法。我的意思是,如果您要发送 5 条垃圾邮件,它将处理第一条消息,然后延迟 10 秒,直到它开始处理第二条消息。我想让它平行。 Task.Delay() 对我来说就像 Thread.Sleep() 一样工作。两者效果相同。

有人在特定频道中写入不包含附件的消息,因此如果机器人看到它,该消息将被重定向到另一个频道。我想删除人的消息,给用户写机器人回复并等待 10 秒钟,然后机器人的答案将被删除。现在它的工作方式就像用户写消息,机器人删除它并停止整个程序 10 秒,而不是任务。所以我可以发送垃圾邮件,例如 10 条消息,机器人会在 100 秒后删除它们,因为程序有延迟

using Discord;
using System;
using System.Threading.Tasks;
using Discord.Commands;
using System.Net.Sockets;

namespace BillyNet
{
    class Program
    {
        DiscordSocketClient discord;
        static void Main(string[] args) => new Program().RunBotAsync().ConfigureAwait(false).GetAwaiter().GetResult();

        public async Task RunBotAsync()
        {
            discord = new DiscordSocketClient();
            string token = "token here";

            discord.Log += Log;
            discord.MessageReceived += MessageReceived;

            await discord.LoginAsync(TokenType.Bot, token);
            await discord.StartAsync();

            await Task.Delay(-1);
        }

        private async Task MessageReceived(SocketMessage message)
        {
            var chat = discord.GetChannel(466671032783077389) as IMessageChannel;
            var redirectChat = discord.GetChannel(458517175536320514) as IMessageChannel;

            if ((message.Attachments.Count < 1) && (message.Channel.Id == chat.Id) && (!message.Author.IsBot))
            {
                var botReply = await message.Channel.SendMessageAsync($"Ваше сообщение было переправлено в канал {MentionUtils.MentionChannel(redirectChat.Id)}." +
                        $"\nВ {MentionUtils.MentionChannel(chat.Id)} запрещены сообщения не содержащие фотографии.");
                await redirectChat.SendMessageAsync($"**[{message.Author.Username}]**: {message.Content}" +
                    $"\n\nСообщение переадресованно из {MentionUtils.MentionChannel(chat.Id)}.");

                await message.DeleteAsync();
                await Task.Delay(10000);
                await botReply.DeleteAsync();
            }
        }

        private Task Log(LogMessage msg)
        {
            Console.WriteLine(msg.ToString());
            return Task.CompletedTask;
        }
    }
}```

【问题讨论】:

  • 任务!= 多线程。异步!=多线程。为什么你期望这里有任何类型的并行性?你知道DiscordSocketClient是怎么实现的吗?也许它会按顺序处理几条消息。

标签: c# .net-core discord


【解决方案1】:

尝试使用 Task.Run 方法启动消息处理,它将异步运行您的函数。像这样更改您的 MessageReceived 方法。

public async Task MessageReceived(SocketMessage message)
    {
        var messageHandleTask = Task.Run(async () =>
        {
            var chat = discord.GetChannel(466671032783077389) as IMessageChannel;
            var redirectChat = discord.GetChannel(458517175536320514) as IMessageChannel;

            if ((message.Attachments.Count < 1) && (message.Channel.Id == chat.Id) && (!message.Author.IsBot))
            {
                var botReply = await message.Channel.SendMessageAsync($"Ваше сообщение было переправлено в канал {MentionUtils.MentionChannel(redirectChat.Id)}." +
                        $"\nВ {MentionUtils.MentionChannel(chat.Id)} запрещены сообщения не содержащие фотографии.");
                await redirectChat.SendMessageAsync($"**[{message.Author.Username}]**: {message.Content}" +
                    $"\n\nСообщение переадресованно из {MentionUtils.MentionChannel(chat.Id)}.");

                await message.DeleteAsync();
                await Task.Delay(10000);
                await botReply.DeleteAsync();
            }
        });
    }

编辑 1: 将新线程实例化更改为 Task.Run 方法。

【讨论】:

  • @НадильКаримов,将异步代码与显式线程混合是一个非常糟糕的主意。如果想将任务卸载到线程池线程,有Task.Run API。
  • @НадильКаримор,我认为messageHandleTask 变量不再有意义
猜你喜欢
  • 2021-05-06
  • 1970-01-01
  • 2020-05-11
  • 2022-01-04
  • 1970-01-01
  • 2020-09-24
  • 2018-07-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多