Asyncio进程阻塞 [英] Asyncio process blocking
问题描述
所以我有一个基本的discord机器人,可以接受输入
So i have a basic discord bot which accepts input
import discord
import asyncio
import threading
loop = asyncio.new_event_loop()
bot = discord.Client()
def run_asyncio_loop(loop):
asyncio.set_event_loop(loop)
loop.run_forever()
Hangman.set_bot(bot)
@bot.event
async def on_message(message):
bot.loop.create_task(Hangman.main(message))
asyncioLoop = threading.Thread(target = run_asyncio_loop, args = (loop,))
asyncioLoop.start()
bot.run(BotConstants.TOKEN)
在此示例中,它调用了hangman游戏,该游戏不会阻止任何东西,因为我已经使用 asyncio.sleep(n)
测试了它,但是当我去做在hangman中的东西时,它将阻止它./p>
In this example it calls the hangman game which does not block anything as i have tested this using asyncio.sleep(n)
but when i go to do a something in hangman it blocks it.
class Hangman():
async def main(message):
await Hangman.make_guess(message)
async def update_score(message):
sheetLoaded = Spreadsheet.load_ws(...)
userExists = Spreadsheet.user_exists(...)
if (not userExists):
Spreadsheet.add_user(...)
Spreadsheet.add_score(...)
await Hangman.bot.send_message(message.channel, msg)
elif (not sheetLoaded):
await Hangman.bot.send_message(message.channel, msg)
async def make_guess(message):
# perform guess
if (matched):
await Hangman.bot.send_message(message.channel, msg)
Hangman.GAMES.pop(message.server.id)
await Hangman.update_score(message)
调用 Hangman.update_score()
时,它将阻止它.因此在分数更新之前它不会处理任何命令,这意味着大约5秒钟左右(不长,但由于很多用户向其发送垃圾邮件,这是一个问题),该机器人不会接受任何其他消息
When Hangman.update_score()
is called it blocks it. so it won't process any commands until the score has been updated which means for about 5 or so seconds (not long but with lots of users spamming it it's an issue) the bot does not accept any other messages
我仍想在继续接受新输入的情况下使流程在后台运行吗?
What am i missing to be able to make the process run in the background while still accept new inputs?
推荐答案
Asyncio仍然是单线程的.事件循环运行的唯一方法是没有其他协程正在积极执行.使用yield from/await暂时暂停协程,使事件循环有工作的机会.因此,除非您使用 yield(来自)
或 await
或 return
调用另一个协程,否则该过程将被阻止.您可以在 Hangman.update_score
的步骤之间添加 await asyncio.sleep(0)
,以将进程阻塞分为多个部分,但这只会确保更少的挂起"时间,实际上并没有加快您的线程速度.
Asyncio is still single-threaded. The only way for the event loop to run is for no other coroutine to be actively executing. Using yield from/await suspends the coroutine temporarily, giving the event loop a chance to work. So unless you call another coroutine using yield (from)
or await
or return
, the process is blocked. You can add await asyncio.sleep(0)
in between steps of Hangman.update_score
to divide the process blocking in multiple parts, but that will only ensure less "hanging" time, not actually speed up your thread.
要使该过程实际上在后台运行,您可以尝试以下方法:
To make the process actually run in the background, you could try something along the lines of:
from concurrent.futures import ProcessPoolExecutor
executor = ProcessPoolExecutor(2)
asyncio.ensure_future(loop.run_in_executor(executor, Hangman.update_score(message)))
这篇关于Asyncio进程阻塞的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!