Search code examples
c#discordbotsdiscord.net

How to Fix "A Reaction handler is blocking the Gateway task"


So I have the problem that when many Reactions get added to a Message in discord I get the following error:
A ReactionAdded handler is blocking the gateway task.

As long as only a few reactions are added everything seems fine but when multiple are added at the same time (or in quick succession) I get the error.

It also seems in general that the ReactionHandler is taking time to realise there was a reaction added. Which should not be because the things I do in the handler are slow (because I don't do much in there)

Necessary Code (There's more but for this problem it's unnecessary I think):

class Program
{
   //some variables
   public static Task Main() => new Program().MainAsync();

   public async Task MainAsync()
   {
      using IHost host = Host.CreateDefaultBuilder()
         //some other code
         .AddSingleton<ReactionHandler>())
         .Build();

      await.RunAsync(host);
   }

   public async Task RunAsync(IHost host)
   {
      using IServiceScope serviceScope = host.Services.CreateScope();
      IServiceProvider provider = serviceScope.ServiceProvider;
      //some other code

      var reactions = provider.GetRequiredService<ReactionHandler>();
      reactions.InitializeAsync();
      //some other code

      await _client.LoginAsync(TokenType.Bot, "Token");
      await _client.StartAsync();

      await Task.Delay(-1);
   }
}
public class ReactionHandler
{
   private readonly DiscordSocketClient _client;

   public ReactionHandler(DiscordSocketClient client)
   {
      _client = client;
   }

   public async Task InitializeAsync()
   {
      _client.ReactionAdded += HandleReationAsync;
      _client.ReactionRemoved += HandleReactionAsync;
   }

   private async Task HandleReactionAsync(Cacheable<IUserMessage, ulong> message, Cacheable<IMessageChannel, ulong> channel, SocketReaction reaction)
   {
      if (reaction.User.Value.IsBot) return;

      Console.WriteLine("Reaction changed");
      //some other code
   }
}

So if there's some information missing (cause I left out some code) just tell me then I add it. Now in the interent I've read simular things happen with the MessageReceived Handler, but their code was so different from mine that I just didn't understand it. Also I've read that this can happen when the code / things I do are slow, but the code above is not that much that it is too slow right.

I hope everything's clear and thanks in advance :)


Solution

  • If I understand the problem correctly, seems like you're eating up all the threads in your app to handle reactions. It might be better to make the ReactionHandler a hosted service then queue reactions to that service so you're not waiting on those threads. This will essentially make ReactionHandler run in the background and process as they come.

    Background tasks with hosted services in ASP.NET Core

    Just do keep in mind that this will be on a completely separate thread so you need to make adjustments to make it a multithreaded app.

    You would convert your handler to a hosted service, use some message queueing solution or roll your own to make requests to the service. Then the client (outside of the hosted service) would then add to the queue for when reactions are received.