python取消任务的方法_python asyncio,如何从另一个线程创建和取消任务

我想你可能需要让你的 add_task 方法知道是否从同一个线程调用事件循环's. That way, if it'以外的线程调用它,你可以直接调用 asyncio.async ,否则,它可以做一些额外的工作从循环's thread to the calling thread. Here'传递任务的一个例子:

import time

import asyncio

import functools

from threading import Thread, current_thread, Event

from concurrent.futures import Future

class B(Thread):

def __init__(self, start_event):

Thread.__init__(self)

self.loop = None

self.tid = None

self.event = start_event

def run(self):

self.loop = asyncio.new_event_loop()

asyncio.set_event_loop(self.loop)

self.tid = current_thread()

self.loop.call_soon(self.event.set)

self.loop.run_forever()

def stop(self):

self.loop.call_soon_threadsafe(self.loop.stop)

def add_task(self, coro):

"""this method should return a task object, that I

can cancel, not a handle"""

def _async_add(func, fut):

try:

ret = func()

fut.set_result(ret)

except Exception as e:

fut.set_exception(e)

f = functools.partial(asyncio.async, coro, loop=self.loop)

if current_thread() == self.tid:

return f() # We can call directly if we're not going between threads.

else:

# We're in a non-event loop thread so we use a Future

# to get the task from the event loop thread once

# it's ready.

fut = Future()

self.loop.call_soon_threadsafe(_async_add, f, fut)

return fut.result()

def cancel_task(self, task):

self.loop.call_soon_threadsafe(task.cancel)

@asyncio.coroutine

def test():

while True:

print("running")

yield from asyncio.sleep(1)

event = Event()

b = B(event)

b.start()

event.wait() # Let the loop's thread signal us, rather than sleeping

t = b.add_task(test()) # This is a real task

time.sleep(10)

b.stop()

首先,我们在 run 方法中保存事件循环的线程id,因此我们可以确定以后是否来自其他线程的 add_task 调用 . 如果从非事件循环线程调用 add_task ,我们使用 call_soon_threadsafe 调用一个函数来调度协程,然后使用 concurrent.futures.Future 将任务传递回调用线程,调用线程等待 Future 的结果 .

关于取消任务的注意事项:当您在 Task 上调用 cancel 时,将在下次运行事件循环时在协同程序中引发 CancelledError . 这意味着任务正在包装的协程将在下次达到屈服点时因异常而中止 - 除非协程捕获 CancelledError 并防止其自身中止 . 另请注意,这仅适用于被包装的函数实际上是可中断的协程;例如,由 BaseEventLoop.run_in_executor 返回的 asyncio.Future 实际上't really be cancelled, because it'可以包围 concurrent.futures.Future ,并且一旦它们的基础函数实际开始执行就无法取消 . 在这些情况下, asyncio.Future 会将其取消,但实际运行在执行程序中的函数将继续运行 .

Edit: 根据Andrew Svetlov的建议,更新了使用 concurrent.futures.Future 而不是 queue.Queue 的第一个示例 .

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值