aysncio

event_loop

一个线程只有一个event_loop

1、get_event_loop() 只能在主线程中创建event_loop,子线程的loop要在主线程通过new_event_loop创建,然后在子线程中使用set_event_loop来设置,如果 在子线程中直接用get_event_loop创建就会报错

RuntimeError: There is no current event loop in thread 'Thread-1'.

2、new_event_loop(),创建另一个event_loop,与get_event_loop不是同一个。

3、set_event_loop(loop),为线程设置一个event_loop为loop,无返回值.

 

wait、 gather

gather(*task),以列表返回异步函数的返回结果

wait(task,timeout)可设置超时时间,分别返回的是完成的futures,和未完成的futures,如果要结果,再通过future.result()来获取。

 

run_coroutine_threadsafe、wrap_future、call_soon_threadsafe

loop.run_until_complete(),任务完成就停止循环

loop.run_forever() ,loop一直运行,直到loop.stop才会停止。loop.close()也不行。

loop.call_soon_threadsafe(),任务完成后调用函数

asyncio.run_coroutine_threadsafe(coroutine,loop),以线程安全的方式运行协程,可实现跨线程调用协程。

asyncio.wrap_future(),创建个新的future与原future连接,只要其中一个完成,另一个也完成。

代码如下

 1 main_loop = asyncio.get_event_loop()       #主线程 创建主循环
 2 sub_loop = asyncio.new_event_loop()        #创建另一个新的循环,用于子线程
 3 task = [asyncio.wrap_future(asyncio.run_coroutine_threadsafe(do_some_work(i, randint(0,4)),sub_loop)) for i in range(4)]  
  #创建任务,将异步程序用asyncio.run_coroutine_threadsafe()函数包装成future,再用asyncio.wrap_future包装成新的future,新future会连到主循环中,所以就可以在主循环中使用run_until_complete来等待子循环完成
4 th = threading.Thread(target=sub_loop.run_forever) #创建子线程,启动循环 5 th.start() 6 print("thread",threading.enumerate()) 7 main_loop.run_until_complete(asyncio.wait(task)) #主循环,直到任务完成结束 8 sub_loop.call_soon_threadsafe(sub_loop.stop) #子循环调用stop,停止异步 9 th.join()                         # 线程结束 10 print("End thread",threading.enumerate())

 

输出:

thread [<Thread(Thread-1, started 13448)>, <_MainThread(MainThread, started 9788)>]
0 Waiting 1
1 Waiting 3
2 Waiting 4
3 Waiting 0
3 Done after 0s
0 Done after 1s
1 Done after 3s
2 Done after 4s
End thread [<_MainThread(MainThread, started 9788)>]

 在子线程内开异步:

先上代码:

 1 async def do_some_work(i,x):
 2     print('{} Waiting {}'.format(i,x))
 3     await asyncio.sleep(x)
 4     print('{} Done after {}s'.format(i,x))
 5     return "haha"
 6 
 7 def start_sub_loop():
 8     sub_sub_loop = asyncio.new_event_loop()
 9     asyncio.set_event_loop(sub_sub_loop)
10     print("create start_sub_loop threads ", threading.enumerate())
11     start = now()
12     task = [asyncio.ensure_future(do_some_work(i, randint(0,4))) for i in range(4)]
13     d,p= sub_sub_loop.run_until_complete(asyncio.wait(task))
14     for i in d:
15         print(i.result())
16     for i in p:
17         print(i)
18 19     print("cost time:",time.time()-start)
20     print("over threads",threading.enumerate())
21 def other_thread():
22     print("create other_thread thread:", threading.enumerate())
23     t = threading.Thread(target=start_sub_loop)
24     t.start()
25     t.join()
26     print("after t.join() threads ",threading.enumerate())
27 28 29 th = threading.Thread(target=other_thread)
30 th.start()
31 th.join()
32 print("End thread",threading.enumerate())

输出:

 1 create other_thread thread: [<_MainThread(MainThread, started 15288)>, <Thread(Thread-1, started 14816)>]
 2 create start_sub_loop threads  [<_MainThread(MainThread, started 15288)>, <Thread(Thread-1, started 14816)>, <Thread(Thread-2, started 15252)>]
 3 0 Waiting 3
 4 1 Waiting 1
 5 2 Waiting 0
 6 3 Waiting 0
 7 2 Done after 0s
 8 3 Done after 0s
 9 1 Done after 1s
10 0 Done after 3s
11 haha
12 haha
13 haha
14 haha
15 cost time: 3.000324249267578
16 over threads [<_MainThread(MainThread, started 15288)>, <Thread(Thread-1, started 14816)>, <Thread(Thread-2, started 15252)>]
17 after t.join() threads  [<_MainThread(MainThread, started 15288)>, <Thread(Thread-1, started 14816)>]
18 End thread [<_MainThread(MainThread, started 15288)>]

上面代码共开了三个线程,只在最后一个线程开协程。其实和在主线程开协程一样,不同的是在主线程可以用get_event_loop,在子线程只能用new_event_loop,和set_event_loo。

 

 

posted @ 2018-11-12 23:06  xinghun85  阅读(873)  评论(0编辑  收藏  举报