首页 > 解决方案 > 如何重置或取消 asyncio.sleep 事件?

问题描述

我正在尝试在不和谐中设置一个可以在计时器上运行的机器人。如果有人输入“!挑战”命令,其中一个将起作用,其中机器人将等待 60 秒以查看是否有人输入“!接受”命令作为响应。如果没有,则说明“挑战被忽略”。重置。或类似的规定。

另一个计时器实际上在游戏过程中运行,并且是一个小时长。但是,输入命令后小时会重置。如果游戏空闲一个小时(一个玩家 DC 或退出),机器人会重置游戏本身。

我有这个使用线程:

        # Initiate a challenge to the room. Opponent is whoever uses the !accept command. This command should be
        # unavailable for use the moment someone !accepts, to ensure no one trolls during a fight.
        if message[:10] == "!challenge":
            msg, opponent, pOneInfo, new_game, bTimer, playerOne = message_10_challenge(channel, charFolder, message, unspoiledArena, character,                   self.game)
            if opponent is not "":
                self.opponent = opponent
            if pOneInfo is not None:
                self.pOneInfo = pOneInfo
                self.pOneTotalHP = self.pOneInfo['thp']
                self.pOneCurrentHP = self.pOneInfo['thp']
                self.pOneLevel = self.pOneInfo['level']
            if new_game != 0:
                self.game = new_game
            if bTimer is True:
                timeout = 60
                self.timer = Timer(timeout, self.challengeTimeOut)
                self.timer.start()
            if playerOne is not "":
                self.playerOne = playerOne
            super().MSG(channel, msg)

和:

        # Response to use to accept a challenge.

       if message == "!accept":
            msg, pTwoInfo, new_game, playerTwo, bTimer, bGameTimer, new_oppenent, token = message_accept(channel, charFolder, unspoiledArena,                                character, self.game, self.opponent, self.pOneInfo)
            if not charFile.is_file():
                super().MSG(channel, "You don't even have a character made to fight.")
            else:
                if new_game is not None:
                    self.game = new_game
                if pTwoInfo is not None:
                    self.pTwoInfo = pTwoInfo
                    self.pTwoTotalHP = self.pTwoInfo['thp']
                    self.pTwoCurrentHP = self.pTwoInfo['thp']
                    self.pTwoLevel = self.pTwoInfo['level']
                if bTimer:
                    self.timer.cancel()
                if bGameTimer:
                    gametimeout = 3600
                    self.gameTimer = Timer(gametimeout, self.combatTimeOut)
                    self.gameTimer.start()
                if new_oppenent is not None:
                    self.opponent = new_oppenent
                if playerTwo is not None:
                    self.playerTwo = playerTwo
                if token is not None:
                    self.token = token
                for msg_item in msg:
                    super().MSG(channel, msg_item)

具有功能:

    def challengeTimeOut(self):
        super().MSG(unspoiledArena, "Challenge was not accepted. Challenge reset.")
        self.game = 0

    def combatTimeOut(self):
        super().PRI('Unspoiled Desire', "!reset")

以上是同一游戏的示例,但在不同的聊天平台上,使用线程来处理计时器。但是我猜 threading 和 discord.py 不是朋友。所以我试图让上面的代码与 discord.py 一起工作,它似乎使用 asyncio。

这个想法是用asyncio.sleep()

if bTimer is true:
     await asyncio.sleep(60)
     self.game = 0
     await ctx.send("Challenge was not accepted. Challenge reset.")

这有效......但它不会停止计时器,所以即使有人!accepts,因此更改bTimerFalse,这将取消计时器:

if bTimer:
     self.timer.cancel()

它仍然会说“挑战未被接受。挑战重置。”

bGameTimer如果我尝试,也会出现同样的问题:

if bGameTimer:
     await asyncio.sleep(3600)
     await ctx.send("!reset")

无论游戏是否完成,游戏都会在 1 小时后硬连线重置。而不是在每转一圈后重置 1 小时计时器,并且仅在经过整整一小时且未发出任何命令时才重置。

有没有办法轻松取消或重置睡眠周期?

标签: python-3.xpython-asynciodiscord.py

解决方案


与您的线程代码等效的 asyncio 代码将是:

...
    if bTimer:
         self.timer = asyncio.create_task(self.challengeTimeout())
...

async def challengeTimeout(self):
     await asyncio.sleep(60)
     self.game = 0
     await ctx.send("Challenge was not accepted. Challenge reset.")

asyncio.create_task()创建一个轻量级的“任务”对象,大致相当于一个线程。它与您的其他协程“并行”运行,您可以通过调用它的cancel()方法来取消它:

if bTimer:
    self.timer.cancel()

推荐阅读