2015-07-02 29 views
1

我使用ASYNCIO在Windows上ASYNCIO傳輸對象寫入/並有一個命名管道的運輸對象的引用:如何執行*同步*讀/從

class DataPipeHandler(asyncio.Protocol): 
    def connection_made(self, trans): 
     self.trans = trans # <<== this is a reference to a transport object of type _ProactorDuplexPipeTransport 

loop = asyncio.get_event_loop() 
server = loop.start_serving_pipe(lambda: DataPipeHandler(), r'\\.\pipe\test-pipe') 

現在我想使用self.trans同步寫入然後從命名管道讀取數據。我怎樣才能做到這一點?

它非常重要,我做這個同步,因爲這是一種RPC調用我使用的是管道(寫的東西並取回響應快)這樣做,我也想塊甚至環的所有其他活動的直到這個「管道RPC調用」返回。 如果我不阻止事件循環的所有其他活動,直到這個RPC調用完成,我將產生不需要的副作用,因爲循環將繼續處理其他我不想處理的事件。

我想要做的事(寫入管道然後讀取)與從事件循環線程調用urllib2.urlopen(urllib2.Request('http://www.google.com')).read()的人非常相似 - 在這裏,所有的事件循環活動都將被阻止,直到我們從遠程獲得響應http服務器。

我知道我可以調用self.trans.write(數據),但這不會將數據同步寫(我的理解它不會阻塞)

感謝。

編輯:繼第一條評論我要補充:

我知道我不應該阻止事件循環,我也可以使用同步原語爲實現我想要的東西。但讓我們說你有事件循環,它並行執行10個不同的活動,其中一個正在做某種RPC(如上所述),其他9個活動應該被阻止,直到完成這個RPC。所以我有2個選項:

(1)按照您對所有這10個活動的建議添加同步原語(鎖定/信號量/條件)以同步它們。 (2)通過阻止寫入然後阻止讀取/去往管道來實現這個RPC。 (假設我相信管道的另一端)

我知道這不是使用事件循環的常用方式,但在我的具體情況下,我認爲(2)更好。 (更簡單的邏輯)

+3

我認爲你做錯了事。你不應該阻止事件循環。如果您需要阻止某些操作執行,請使用像asyncio.Lock,asyncio.Semapthore,asyncio這樣的同步原語。條件'等 –

+0

可以說你有第11次活動,永遠不應該被阻止。對於同步原語,您仍然可能會阻止您的9個活動並保持第10和第11個運行。 –

+0

我明白使用同步原語可以讓我更靈活地控制哪些活動將被阻止,哪些不會被阻止。但就我而言,我有上述的固定情況。 (在進行RPC時需要阻止所有其他事件循環活動) – user3402399

回答

1

我認爲你必須使用線程同步原語來確保整個循環(當前線程)被阻塞。我認爲最好的報價是使用線程隊列和連接功能。