本文介绍了扩展tornado.gen.Task的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是一个愚蠢的websocket时钟的有趣之处:

Here's the interesting bits of a stupid websocket clock:

class StupidClock(websocket.WebSocketHandler):
    clients = {}

    @web.asynchronous
    @gen.coroutine
    def open(self):
        self.is_open = True
        def enqueue(callback=None):
            self.__class__.clients[self] = callback
        while self.is_open:
            # This is the most interesting part!
            msg = yield gen.Task(enqueue)
            self.write_message(msg)

    def on_close(self):
        self.is_open = False
        del self.__class__.clients[self]

    @classmethod
    def periodic_update(cls):
        msg = time.time()
        # copy and clear before iterating to avoid infinite growth!
        clients = cls.clients.copy()
        cls.clients.clear()

        for obj, callback in clients.items():
            if obj.is_open:
                callback(msg)

# all the routing and application setup omitted...

loop = ioloop.IOLoop.instance()
cb = ioloop.PeriodicCallback(StupidClock.periodic_callback, 1,
                             io_loop=loop)
cb.start()
loop.start()

所以我的问题是关于解构此语句:

So my question is about deconstructing this statement:

msg = yield gen.Task(enqueue)

文档中的内容与以下内容相同:

From the documentation, it's the same as:

result = yield gen.Task(func, args)
# is the same as
func(args, callback=(yield gen.Callback(key)))
result = yield gen.Wait(key)

我很清楚第一种形式(只有一个 yield 表达式)发生了什么,但是为什么我必须将控制权交给Tornado来创建 gen.Callback 对象?

It's quite clear to me what's happening with the first form (only one yield expression), but why must I yield control to Tornado to create a gen.Callback object?

一个单独的 yield 表达式如何等效于两个 yield 表达式?难道不能控制两次龙卷风的收益吗?但是,在 gen.Task 表单中,我只产生一次控制!

How can one single yield expression be equivalent to two yield expressions? Mustn't control yield to Tornado two times? Yet, in the gen.Task form, I only yield control once!

推荐答案

调用 yield gen.Callback 时,它会短暂地将控制权转移到Tornado,但是Tornado立即返回您的代码.这只是与协程调度程序进行通信的一种方式,而无需使用全局(或线程局部)变量.它使用这种奇怪的模式,因此可以与 gen 模块之前的库一起使用,而对协程一无所知.对于较新的代码(自Tornado 3.0起),推荐的模式是异步函数返回 Future (如果使用 @ gen.coroutine ,则会自动发生),这将使它们可以在没有 gen.Task gen.Callback 的协程中使用.

When you call yield gen.Callback it briefly transfers control to Tornado, but Tornado immediately returns to your code. It's just a way to communicate with the coroutine scheduler without using global (or thread-local) variables. It uses this weird pattern so it can work with libraries that predated the gen module and don't know anything about coroutines. For newer code (since Tornado 3.0), the recommended pattern has been for asynchronous functions to return a Future (which happens automatically if you use @gen.coroutine), which lets them be used in coroutines without gen.Task or gen.Callback.

这篇关于扩展tornado.gen.Task的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-05 11:22
查看更多