簡體   English   中英

為什么異步代碼沒有停止?

[英]Why doesn't this async code stop?

以下代碼段分別具有兩個協程,分別用於服務器和客戶端。 客戶端協程具有在10秒后中斷while循環的邏輯,服務器應在15秒后停止。

當我運行腳本時,它不會停止,理想情況下,它應該在15秒后停止,但這不會發生。

import asyncio
import time
import zmq
import zmq.asyncio

zmq.asyncio.install()

ctx = zmq.asyncio.Context()


server_socket = ctx.socket(zmq.REP)
client_socket = ctx.socket(zmq.REQ)

server_socket.bind("tcp://127.0.0.1:8899")
client_socket.connect("tcp://127.0.0.1:8899")

t0 = time.time()


@asyncio.coroutine
def server_coroutine():

    while True:
        msg = yield from server_socket.recv_string()
        print(msg)
        msg = "Server:: {}".format(msg)
        yield from server_socket.send_string(msg)
        t1 = time.time()
        elapsed_time = t1 - t0
        # print('elapsed time is {}'.format(elapsed_time))
        if elapsed_time > 15:
            print("Breaking Server loop")
            break

@asyncio.coroutine
def client_coroutine():
    counter = 0
    while True:
        yield from asyncio.sleep(2)
        msg = 'Message: {}'.format(counter)
        yield from client_socket.send_string(msg)
        res = yield from client_socket.recv_string()
        print(res)
        t1 = time.time()
        elapsed_time = t1 - t0
        print('elapsed time is {}'.format(elapsed_time))
        if elapsed_time > 10:
            print("Breaking Client loop")
            break
        counter += 1


if __name__ == '__main__':

    loop = asyncio.get_event_loop()

    loop.run_until_complete(asyncio.gather(
        asyncio.ensure_future(server_coroutine()),
        asyncio.ensure_future(client_coroutine())
    ))

如果您運行代碼,您將看到類似以下內容:

Server:: Message: 4
elapsed time is 10.022311687469482
Breaking Client loop

好的, client_coroutine成功完成,但是此時server_coroutine處於什么狀態? 它停留在此行msg = yield from server_socket.recv_string()等待從server_socket字符串的可能性,但是不會發生,因為已經沒有客戶端可以發送它了! 而且由於您的事件循環一直運行到兩個協程完成,所以它將永遠運行。

這是最簡單的解決方法:

@asyncio.coroutine
def server_coroutine():
    while True:
        msg = yield from server_socket.recv_string()
        if msg == 'CLOSE':  # LOOK HERE 1
            break
        print(msg)
        msg = "Server:: {}".format(msg)
        yield from server_socket.send_string(msg)
        t1 = time.time()
        elapsed_time = t1 - t0
        # print('elapsed time is {}'.format(elapsed_time))
        if elapsed_time > 15:
            print("Breaking Server loop")
            break

@asyncio.coroutine
def client_coroutine():
    counter = 0
    while True:
        yield from asyncio.sleep(2)
        msg = 'Message: {}'.format(counter)
        yield from client_socket.send_string(msg)
        res = yield from client_socket.recv_string()
        print(res)
        t1 = time.time()
        elapsed_time = t1 - t0
        print('elapsed time is {}'.format(elapsed_time))
        if elapsed_time > 10:
            print("Breaking Client loop")
            yield from client_socket.send_string('CLOSE')  # LOOK HERE 2
            break
        counter += 1

請注意,此修復程序僅用於演示問題以及解決該問題的一種可能方法。

在現實生活中,我認為您可能會想做一些不同的事情:可能會為協程設置超時,以確保如果客戶端/服務器停止響應,協程不會永遠卡住。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM