0

我正在学习 Trio 教程,并制作了一个echo-client,它将消息发送到echo 服务器10 秒:

async def sender(client_stream, flag):
    print("sender: started!")
    end_time = time.time() + 10
    while time.time() < end_time:
        data = b"async can sometimes be confusing, but I believe in you!"
        print("sender: sending {!r}".format(data))
        await client_stream.send_all(data)
        await trio.sleep(0)
    flag = False
    print("Left the while 10 seconds loops")

并等待响应flag为“真”。

async def receiver(client_stream, flag):
    print("receiver: started!")
    while(flag):
        data = await client_stream.receive_some()
        print("receiver: got data {!r}".format(data))
    print("receiver: connection closed")
    sys.exit()

问题是有时程序会data = await client_stream.receive_some()因为与变量有关的并发问题而挂起flag

如何从sender协程向协程发送信号receiver

这是您可以运行的整个程序。

4

1 回答 1

1

它不仅有时挂在那里,而且一直挂在那里,因为flag变量 inreceiver()永远不会改变。我认为您的印象是它以某种方式在receiver()and之间共享sender()。它不是。

您可以解决此问题的最简单方法是将其传递到容器中:

async def sender(client_stream, flag):
    print("sender: started!")
    end_time = time.time() + 10
    while time.time() < end_time:
        data = b"async can sometimes be confusing, but I believe in you!"
        print("sender: sending {!r}".format(data))
        await client_stream.send_all(data)
        await trio.sleep(0)
    flag[0] = False
    print("Left the while 10 seconds loops")

async def receiver(client_stream, flag):
    print("receiver: started!")
    while flag[0]:
        data = await client_stream.receive_some()
        print("receiver: got data {!r}".format(data))
    print("receiver: connection closed")
    sys.exit()

async def start_server():
    print("parent: connecting to 127.0.0.1:{}".format(PORT))
    client_stream = await trio.open_tcp_stream("127.0.0.1", PORT)
    flag = [False]
    async with client_stream:
        async with trio.open_nursery() as nursery:
            print("parent: spawning sender...")
            nursery.start_soon(sender, client_stream, flag)

            print("parent: spawning receiver...")
            nursery.start_soon(receiver, client_stream, flag)

一个更优雅的解决方案是关闭流sender()并捕获:ClosedResourceErrorreceiver()

async def sender(client_stream):
    print("sender: started!")
    data = b"async can sometimes be confusing, but I believe in you!"
    with trio.move_on_after(10):
        print("sender: sending {!r}".format(data))
        await client_stream.send_all(data)

    await client_stream.aclose()
    print("Left the while 10 seconds loops")

async def receiver(client_stream):
    print("receiver: started!")
    try:
        async for data in client_stream:
            print("receiver: got data {!r}".format(data))
    except trio.ClosedResourceError:
        print("receiver: connection closed")

注意你甚至不需要sys.exit()程序结束。

于 2020-08-02T21:53:23.543 回答