Discord.СЕТЬ ожидает внешнюю команду

#c# #asynchronous #discord

#c# #асинхронный #Discord

Вопрос:

Я программирую Discord bot и столкнулся с большой проблемой. Я программирую RPG-бота, поэтому мне нужно очень часто записывать HP игрока и hp врага, поэтому я создал функцию.

 private void showHP(CommandEventArgs e)
{
    client.ExecuteAndWait(async() =>
    {
        await e.Channel.SendMessage(userInside   " - "   player.HP);
    });
}
  

Это CommandEventArgs e исходит из командной функции, поскольку мне нужно получить доступ к каналу, где была выполнена эта команда.

 commands.CreateCommand("attack").Do(async (e) =>
{
    await e.Channel.SendMessage("You have attacked");
    showHP(e);
}
  

Кажется, все работает довольно хорошо… Пока она не будет выполнена. Весь бот зависает и находится в бесконечном ожидании, поэтому я думаю, что неправильно использовал команды async и wait. Если я вообще их не использую, сообщение переходит в режим ожидания.

Комментарии:

1. Или проблема в использовании discord. Выполнить и ждать?

Ответ №1:

client.ExecuteAndWait() блокирует вызывающий контекст до тех пор, пока родительский DiscordClient (в вашем случае client ) не отключится.

Это неправильный способ создания асинхронного контекста — самым простым способом сделать это было бы обернуть ваш код в Task.Run , вот так:

 private void showHP(CommandEventArgs e)
{
    Task.Run(async () => {
        await e.Channel.SendMessage($"{userInside} - {player.HP}");
    });
}
  

Комментарии:

1. Еще лучше, просто с void showHP(){ e.Channel.SendMessage($"{userInside} - {player.HP}"); }

2. @Gusman хороший, но не конкретно «лучший» код операционной системы async

3. Функция недействительна, поэтому она не будет ждать завершения задачи, вызов асинхронной задачи без await приводит к тому же результату, это даже более эффективно, поскольку больше нет возврата к ожидающему коду, так что да, это лучше.

Ответ №2:

Если вы хотите следовать правильному шаблону для асинхронности, измените свой код следующим образом:

 private Task showHP(CommandEventArgs e)
{
    return e.Channel.SendMessage($"{userInside} - {player.HP}");

}
  

И выполните вызов следующим образом:

 commands.CreateCommand("attack")
            .Do(async (e) =>
            {
                await e.Channel.SendMessage("You have attacked");
                await showHP(e);
            }
  

Создавать задачу для запуска функции как асинхронной и не ожидать выполнения этой задачи просто бесполезно, просто вызовите функцию async без await и верните задачу, это помешает планировщику задач разделять код на разные контекстные переключатели.