Asyncio进程阻塞 [英] Asyncio process blocking

查看:54
本文介绍了Asyncio进程阻塞的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以我有一个基本的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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆