2016-03-31 25 views
2

Python 3.5'de asyncio'yla ilk adımları atıyorum ve beni rahatsız eden bir sorun var. Açıkçası tam olarak anlaşılmamış koroutinler ...Python'da çok iş parçacıklı asyncio

İşte yaptığım şeyin basitleştirilmiş bir sürümüdür.

Sınıfımda yeni bir iş parçacığı oluşturan open() yöntemim var. Bu iş parçacığı içinde yeni bir olay döngüsü ve bazı ana bilgisayara bir yuva bağlantısı oluşturuyorum. Sonra sonsuza dek döngü çalışmasına izin verdim.

def open(self): 
    # create thread 
    self.thread = threading.Thread(target=self._thread) 
    self.thread.start() 
    # wait for connection 
    while self.protocol is None: 
     time.sleep(0.1) 

def _thread(self): 
    # create loop, connection and run forever 
    self.loop = asyncio.new_event_loop() 
    coro = self.loop.create_connection(lambda: MyProtocol(self.loop), 
             'somehost.com', 1234) 
    self.loop.run_until_complete(coro) 
    self.loop.run_forever() 

şimdi oldukça basit bir bağlantı olduğunu Durdurma, sadece ana iş parçacığı gelen döngüyü durdurmak:

loop.call_soon_threadsafe(loop.stop) 

Ne yazık ki bazı temizlik yapmak gerekiyor, özellikle ben kesmeden önce bir kuyruk boşaltmak gerekir sunucu. Bu yüzden MyProtocol bu durağı() yöntemi gibi bir şey denedim:

class MyProtocol(asyncio.Protocol): 
    def __init__(self, loop): 
     self._loop = loop 
     self._queue = [] 

    async def stop(self): 
     # wait for all queues to empty 
     while self._queue: 
      await asyncio.sleep(0.1) 
     # disconnect 
     self.close() 
     self._loop.stop() 
kuyruk protokol data_received() yöntemi içinde boşaltılmış olur

yüzden sadece asyncio ile while döngüsü kullanarak bunun olmasını beklemek istiyorum .sleep() çağrısı. Sonrasında bağlantıyı kapatıp döngüyü durdururum.

Ancak bu yöntemi ana iş parçacığından nasıl çağırıp beklerim? Ben aşağıdakileri çalıştı, ancak bunların hiçbiri (protokol şu anda kullanılan MyProtocol örneği olan) çalışmıyor gibi görünüyor:

loop.call_soon_threadsafe(protocol.stop) 
loop.call_soon_threadsafe(functools.partial(asyncio.ensure_future, protocol.stop(), loop=loop)) 
asyncio.ensure_future(protocol.stop(), loop=loop) 

kimse burada bana yardım edebilir? Teşekkürler!

cevap

4

Temel olarak, farklı iş parçacığı döngüsünde koroutini zamanlamak istiyorsunuz. Sen run_coroutine_threadsafe kullanabilirsiniz:

future = asyncio.run_coroutine_threadsafe(protocol.stop, loop=loop) 
future.result() # wait for results 

Veya eski tarz async gibi https://stackoverflow.com/a/32084907/681044

import asyncio 
from threading import Thread 

loop = asyncio.new_event_loop() 

def f(loop): 
    asyncio.set_event_loop(loop) 
    loop.run_forever() 

t = Thread(target=f, args=(loop,)) 
t.start()  

@asyncio.coroutine 
def g(): 
    yield from asyncio.sleep(1) 
    print('Hello, world!') 

loop.call_soon_threadsafe(asyncio.async, g()) 
+0

Works, bir cazibe gibi, teşekkürler! –

İlgili konular