Why can a web socket only be read from the request handler task?

The docs currently state:

Reading from the WebSocket ( await ws.receive() ) must only be done inside the request handler task

That verbiage was introduced in this PR: https://github.com/aio-libs/aiohttp/pull/647. Before that PR the verbiage was:

You must use the only websocket task for both reading (e.g await ws.receive()) and writing but may have multiple writer tasks which can only send data asynchronously (by ws.send_str('data') for example).

Can someone confirm or deny if I am allowed to call receive from a task other than the request handling task? Only one task will call receive in this setting.

Specifically, I want to write this. Is it invalid because the receive occurs inside a task other than the request handling task?

class WebSocketKeepAliveContextManager:
    def __init__(self, ws):
        self.ws = ws
        self.task = None

    async def __aenter__(self):
        self.task = asyncio.create_task(self.ws.receive())

    async def __aexit__(self, exc_type, exc, tb):
        if self.task.done():
            message = self.task.result()
            raise ValueError(f'unexpected message during keepalive: {message}')

def keep_ws_alive(ws):
    return WebSocketKeepAliveContextManager(ws)

# ...
    async with keep_ws_alive(ws):
        await long_running_activity()

The answer is: to support multiple writers WebSockerResponse should support internal messages queue which is very not obvious and, in general, requires some API for the queue introspection and manipulation.

It overcomplicates the implementation at least. If you need multiple producers – you can implement it with asyncio.Queue.
It should work pretty well for simple cases.