Python threading.Thread.join()是阻塞的

时间:2016-11-29 07:47:43

标签: python multithreading python-3.x python-asyncio

我正在使用异步编程,并根据此线程中的一些想法编写了一个小包装类,用于线程安全执行协同例程:python asyncio, how to create and cancel tasks from another thread。经过一些调试后,我发现它在调用Thread类的join()函数时挂起(我只是为了测试而覆盖它)。想到我犯了一个错误,我基本上复制了OP所说的代码,并对其进行了测试以找到同样的问题。

他轻微改动的代码:

import threading
import asyncio
from concurrent.futures import Future
import functools

class EventLoopOwner(threading.Thread):
    class __Properties:
        def __init__(self, loop, thread, evt_start):
            self.loop = loop
            self.thread = thread
            self.evt_start = evt_start

    def __init__(self):
        threading.Thread.__init__(self)
        self.__elo = self.__Properties(None, None, threading.Event())

    def run(self):
        self.__elo.loop = asyncio.new_event_loop()
        asyncio.set_event_loop(self.__elo.loop)
        self.__elo.thread = threading.current_thread()
        self.__elo.loop.call_soon_threadsafe(self.__elo.evt_start.set)
        self.__elo.loop.run_forever()

    def stop(self):
        self.__elo.loop.call_soon_threadsafe(self.__elo.loop.stop)

    def _add_task(self, future, coro):
        task = self.__elo.loop.create_task(coro)
        future.set_result(task)

    def add_task(self, coro):
        self.__elo.evt_start.wait()
        future = Future()
        p = functools.partial(self._add_task, future, coro)
        self.__elo.loop.call_soon_threadsafe(p)
        return future.result()  # block until result is available

    def cancel(self, task):
        self.__elo.loop.call_soon_threadsafe(task.cancel)

async def foo(i):
    return 2 * i

async def main():
    elo = EventLoopOwner()
    elo.start()

    task = elo.add_task(foo(10))
    x = await task

    print(x)
    elo.stop(); print("Stopped")
    elo.join(); print("Joined")  # note: giving it a timeout does not fix it

if __name__ == "__main__":
    loop = asyncio.new_event_loop()
    asyncio.set_event_loop(loop)
    assert isinstance(loop, asyncio.AbstractEventLoop)
    try:
        loop.run_until_complete(main())
    finally:
        loop.close()

我运行它的时间大约有50%,它只是拖延并说“停止”#34;但不是"加入"。我做了一些调试,发现它与Task本身发送异常的时间相关。这并不是每次都会发生,但由于它是在我调用threading.Thread.join()时发生的,我必须假设它与循环的破坏有关。可能导致这种情况的原因是什么?

例外情况就是:"cannot join current thread"告诉我.join() 有时 在我调用它的线程上运行有时来自ELO主题。

发生了什么,我该如何解决?

我正在使用Python 3.5.1。

注意:这不会在IDE One上复制:http://ideone.com/0LO2D9

enter image description here

0 个答案:

没有答案