使用 asyncio 的非阻塞 I/O [英] Non-blocking I/O with asyncio

查看:50
本文介绍了使用 asyncio 的非阻塞 I/O的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用 Pygame 和 asyncio 编写网络游戏,但我不知道如何避免读取挂起.这是我的客户端代码:

I'm trying to write a networked game with Pygame and asyncio, but I can't work out how to avoid hanging on reads. Here is my code for the client:

@asyncio.coroutine
def handle_client():
    print("Connected!")
    reader, writer = yield from asyncio.open_connection('localhost', 8000)
    while True:
        mouse_up = False
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()                
            elif event.type == pygame.MOUSEBUTTONUP:
                mouse_up = True

        if mouse_up:
            print("Writing")
            writer.write(b"Mouse up")
        print("Waiting to read")
        line = yield from reader.read(2**12)
        print(line.decode())

    writer.close()

这挂在 line = yield from reader.read(2**12) 行上.我以前认为 asyncio 的要点是它是非阻塞的,所以如果没有任何数据要读取,它就会继续执行.我现在明白事实并非如此.

This hangs on the line line = yield from reader.read(2**12). I previously thought that the point of asyncio was that it was non-blocking, and so if there wasn't any data to read it would just continue executing. I see now that this isn't the case.

如何将 asyncio 网络代码与 Pygame 绘图和事件代码集成?

How do I integrate the asyncio networking code with the Pygame drawing and event code?

推荐答案

yield from 的要点是将执行切换到 asyncio 的事件循环 以阻止当前协程,直到结果可用.要在不阻塞当前协程的情况下安排任务,您可以使用 asyncio.async().

The point of yield from is to switch the execution to the asyncio's event loop and to block the current coroutine until the result is available. To schedule a task without blocking the current coroutine, you could use asyncio.async().

在不阻塞 pygame 循环的情况下打印读取到的数据:

To print read-so-far data without blocking the pygame loop:

@asyncio.coroutine
def read(reader, callback):
    while True:
        data = yield from reader.read(2**12)
        if not data: # EOF
            break
        callback(data)

@asyncio.coroutine
def echo_client():
    reader, ...
    chunks = []
    asyncio.async(read(reader, chunks.append))
    while True:
        pygame.event.pump() # advance pygame event loop
        ...
        if chunks: # print read-so-far data
            print(b''.join(chunks).decode())
            del chunks[:]
        yield from asyncio.sleep(0.016) # advance asyncio loop

while 循环内不应有阻塞调用.

There should be no blocking calls inside the while loop.

read()sleep() 协程在同一个线程中并发运行(显然你也可以同时运行其他协程).

read() and sleep() coroutines run concurrently in the same thread (obviously you could run other coroutines concurrently too).

这篇关于使用 asyncio 的非阻塞 I/O的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆