在异步龙卷风请求处理程序中创建的线程的联接位置



这个让我有点困惑。 对 python 中的龙卷风和线程相当陌生,所以我可能完全偏离了我在这里尝试做的事情。

可能最好从一些简化的代码开始:

class Handler(tornado.web.RequestHandler):
  def perform(self):
     #do something cuz hey, we're in a thread!
  def initialize(self):
    self.thread = None
  @tornado.web.asynchronous
  def post(self):
    self.thread = threading.Thread(target=self.perform)
    self.thread.start()
    self.write('In the request')
    self.finish()
  def on_connection_close(self):
    logging.info('In on_connection_close()')
    if self.thread:
      logging.info('Joining thread: %s' % (self.thread.name))
      self.thread.join()

我的问题是on_connection_close永远不会被调用,请求得到很好的处理。 其次,我是否在以这种方式引入线程时做了什么可怕的事情?

我相信

Thread.join()会阻塞直到线程完成,这可能是你想避免的事情。您可以对处理程序进行线程回调,而不是联接。

使用线程时,请注意 tornado 不是线程安全的,因此不能从线程使用任何 RequestHandler(例如)方法。

这对我有用:

import functools
import time
import threading
import logging
import tornado.web
import tornado.websocket
import tornado.locale
import tornado.ioloop
class Handler(tornado.web.RequestHandler):
    def perform(self, callback):
        #do something cuz hey, we're in a thread!
        time.sleep(5)
        output = 'foo'
        tornado.ioloop.IOLoop.instance().add_callback(functools.partial(callback, output))
    def initialize(self):
        self.thread = None
    @tornado.web.asynchronous
    def get(self):
        self.thread = threading.Thread(target=self.perform, args=(self.on_callback,))
        self.thread.start()
        self.write('In the request')
        self.flush()
    def on_callback(self, output):
        logging.info('In on_callback()')
        self.write("Thread output: %s" % output)
        self.finish()
application = tornado.web.Application([
    (r"/", Handler),
])
if __name__ == "__main__":
    application.listen(8888)
    tornado.ioloop.IOLoop.instance().start()

您可以使用 curl --no-buffer localhost:8888 .某些浏览器(Safari)似乎在显示任何输出之前等待连接关闭,这让我失望了一段时间。

AFAIK,仅当客户端终止连接时才调用on_connection_close,这可能会解释您的问题。关于线程,我不知道你想做什么,但我不明白你为什么要在 Tornado 请求中创建线程,因为 Tornado 的优点之一就是你不必使用线程。如果我在您的示例中添加一个join,我会将其放在self.finish()之前,但是,您可能可以省略它......这将取决于您要对线程执行的操作,但请记住,Tornado 是单线程的,如果线程在join()到来时尚未完成,整个过程将阻塞。

最新更新