title: add_callback with thread pool, but Exception about "Cannot write() after finish()."
body: <p>I'm using thread pool while using Tornado to do some work. This is the code:</p>
  
  <p><strong>common/thread_pool.py</strong></p>
  
  <pre><code>import tornado.ioloop
  
  class Worker(threading.Thread):
      def __init__(self, queue):
          threading.Thread.__init__(self)
          self._queue = queue
  
      def run(self):
          logging.info('Worker start')
          while True:
              content = self._queue.get()
              if isinstance(content, str) and content == 'quit':
                  break
              #content: (func, args, on_complete)
              func = content[0]
              args = content[1]
              on_complete = content[2]
              resp = func(args)
              tornado.ioloop.IOLoop.instance().add_callback(lambda: on_complete(resp))
              #i dont know is correct to call this
              #self._queue.task_done()
          logging.info('Worker stop')
  
  class WorkerPool(object):
      _workers = []
      def __init__(self, num):
          self._queue = Queue.Queue()
          self._size = num
  
      def start(self):
          logging.info('WorkerPool start %d' % self._size)
          for _ in range(self._size):
              worker = Worker(self._queue)
              worker.start()
              self._workers.append(worker)
  
      def stop(self):
          for worker in self._workers:
              self._queue.put('quit') 
          for worker in self._workers:
              worker.join()
          logging.info('WorkerPool stopd')
  
      def append(self, content):
          self._queue.put(content)
  </code></pre>
  
  <p><strong>gateway.py</strong></p>
  
  <pre><code>import tornado.ioloop
  import tornado.web
  
  from common import thread_pool
  
  workers = None
  
  class MainServerHandler(tornado.web.RequestHandler):
      @tornado.web.asynchronous
      def get(self):
          start_time = time.time()
          method = 'get'
          content = (self.handle, (method, self.request, start_time), self.on_complete)
          workers.append(content)
  
      @tornado.web.asynchronous
      def post(self):
          start_time = time.time()
          method = 'post'
          content = (self.handle, (method, self.request, start_time), self.on_complete)
          workers.append(content)
  
      def handle(self, args):
          method, request, start_time = args
          #for test, just return
          return 'test test'
  
      def on_complete(self, res):
          logging.debug('on_complete')
          self.write(res)
          self.finish()
          return        
  
  def main(argv):  
      global workers
      workers = thread_pool.WorkerPool(conf_mgr.thread_num)
      workers.start()
  
      application = tornado.web.Application([(r"/", MainServerHandler)])
      application.listen(8888)
      tornado.ioloop.IOLoop.instance().start()
  
  if __name__ == "__main__":
      main(sys.argv[1:])
  </code></pre>
  
  <p>When I make many concurrent requests, I get this error:</p>
  
  <pre><code>ERROR: 2014-09-15 18:04:03: ioloop.py:435 * 140500107065056 Exception in callback &lt;tornado.stack_context._StackContextWrapper object at 0x7fc8b4d6b9f0&gt;
  
    Traceback (most recent call last):
       File "/home/work/nlp_arch/project/ps/se/nlp-arch/gateway/gateway/../third-party/tornado-2.4.1/tornado/ioloop.py", line 421, in _run_callback
         callback()
       File "/home/work/nlp_arch/project/ps/se/nlp-arch/gateway/gateway/../common/thread_pool.py", line 39, in &lt;lambda&gt;
         tornado.ioloop.IOLoop.instance().add_callback(lambda: on_complete(resp))
       File "/home/work/nlp_arch/project/ps/se/nlp-arch/gateway/gateway/gateway.py", line 92, in on_complete
         self.write(res)
       File "/home/work/nlp_arch/project/ps/se/nlp-arch/gateway/gateway/../third-party/tornado-2.4.1/tornado/web.py", line 489, in write
        raise RuntimeError("Cannot write() after finish().  May be caused "
    RuntimeError: Cannot write() after finish().  May be caused by using async operations without the @asynchronous decorator.
  </code></pre>
  
  <p>But I didn't call <code>write</code> after <code>finish</code>. I'm also using the <code>@asynchronous</code> decorator. At the same time, in the logs I see that <code>write</code>/<code>finish</code> is called by same thread.</p>