#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 и верните задачу, это помешает планировщику задач разделять код на разные контекстные переключатели.