def join(self, timeout=None, propagate=True, interval=0.5, callback=None, no_ack=True):
    'Gathers the results of all tasks as a list in order.\n\n        .. note::\n\n            This can be an expensive operation for result store\n            backends that must resort to polling (e.g. database).\n\n            You should consider using :meth:`join_native` if your backend\n            supports it.\n\n        .. warning::\n\n            Waiting for tasks within a task may lead to deadlocks.\n            Please see :ref:`task-synchronous-subtasks`.\n\n        :keyword timeout: The number of seconds to wait for results before\n                          the operation times out.\n\n        :keyword propagate: If any of the tasks raises an exception, the\n                            exception will be re-raised.\n\n        :keyword interval: Time to wait (in seconds) before retrying to\n                           retrieve a result from the set.  Note that this\n                           does not have any effect when using the amqp\n                           result store backend, as it does not use polling.\n\n        :keyword callback: Optional callback to be called for every result\n                           received.  Must have signature ``(task_id, value)``\n                           No results will be returned by this function if\n                           a callback is specified.  The order of results\n                           is also arbitrary when a callback is used.\n                           To get access to the result object for a particular\n                           id you will have to generate an index first:\n                           ``index = {r.id: r for r in gres.results.values()}``\n                           Or you can create new result objects on the fly:\n                           ``result = app.AsyncResult(task_id)`` (both will\n                           take advantage of the backend cache anyway).\n\n        :keyword no_ack: Automatic message acknowledgement (Note that if this\n            is set to :const:`False` then the messages *will not be\n            acknowledged*).\n\n        :raises celery.exceptions.TimeoutError: if ``timeout`` is not\n            :const:`None` and the operation takes longer than ``timeout``\n            seconds.\n\n        '
    assert_will_not_block()
    time_start = monotonic()
    remaining = None
    results = []
    for result in self.results:
        remaining = None
        if timeout:
            remaining = (timeout - (monotonic() - time_start))
            if (remaining <= 0.0):
                raise TimeoutError('join operation timed out')
        value = result.get(timeout=remaining, propagate=propagate, interval=interval, no_ack=no_ack)
        if callback:
            callback(result.id, value)
        else:
            results.append(value)
    return results
Gathers the results of all tasks as a list in order.

.. note::

    This can be an expensive operation for result store
    backends that must resort to polling (e.g. database).

    You should consider using :meth:`join_native` if your backend
    supports it.

.. warning::

    Waiting for tasks within a task may lead to deadlocks.
    Please see :ref:`task-synchronous-subtasks`.

:keyword timeout: The number of seconds to wait for results before
                  the operation times out.

:keyword propagate: If any of the tasks raises an exception, the
                    exception will be re-raised.

:keyword interval: Time to wait (in seconds) before retrying to
                   retrieve a result from the set.  Note that this
                   does not have any effect when using the amqp
                   result store backend, as it does not use polling.

:keyword callback: Optional callback to be called for every result
                   received.  Must have signature ``(task_id, value)``
                   No results will be returned by this function if
                   a callback is specified.  The order of results
                   is also arbitrary when a callback is used.
                   To get access to the result object for a particular
                   id you will have to generate an index first:
                   ``index = {r.id: r for r in gres.results.values()}``
                   Or you can create new result objects on the fly:
                   ``result = app.AsyncResult(task_id)`` (both will
                   take advantage of the backend cache anyway).

:keyword no_ack: Automatic message acknowledgement (Note that if this
    is set to :const:`False` then the messages *will not be
    acknowledged*).

:raises celery.exceptions.TimeoutError: if ``timeout`` is not
    :const:`None` and the operation takes longer than ``timeout``
    seconds.
def join(self, timeout=None, propagate=True, interval=0.5, callback=None, no_ack=True):
    'Gathers the results of all tasks as a list in order.\n\n        .. note::\n\n            This can be an expensive operation for result store\n            backends that must resort to polling (e.g. database).\n\n            You should consider using :meth:`join_native` if your backend\n            supports it.\n\n        .. warning::\n\n            Waiting for tasks within a task may lead to deadlocks.\n            Please see :ref:`task-synchronous-subtasks`.\n\n        :keyword timeout: The number of seconds to wait for results before\n                          the operation times out.\n\n        :keyword propagate: If any of the tasks raises an exception, the\n                            exception will be re-raised.\n\n        :keyword interval: Time to wait (in seconds) before retrying to\n                           retrieve a result from the set.  Note that this\n                           does not have any effect when using the amqp\n                           result store backend, as it does not use polling.\n\n        :keyword callback: Optional callback to be called for every result\n                           received.  Must have signature ``(task_id, value)``\n                           No results will be returned by this function if\n                           a callback is specified.  The order of results\n                           is also arbitrary when a callback is used.\n                           To get access to the result object for a particular\n                           id you will have to generate an index first:\n                           ``index = {r.id: r for r in gres.results.values()}``\n                           Or you can create new result objects on the fly:\n                           ``result = app.AsyncResult(task_id)`` (both will\n                           take advantage of the backend cache anyway).\n\n        :keyword no_ack: Automatic message acknowledgement (Note that if this\n            is set to :const:`False` then the messages *will not be\n            acknowledged*).\n\n        :raises celery.exceptions.TimeoutError: if ``timeout`` is not\n            :const:`None` and the operation takes longer than ``timeout``\n            seconds.\n\n        '
    assert_will_not_block()
    time_start = monotonic()
    remaining = None
    results = []
    for result in self.results:
        remaining = None
        if timeout:
            remaining = (timeout - (monotonic() - time_start))
            if (remaining <= 0.0):
                raise TimeoutError('join operation timed out')
        value = result.get(timeout=remaining, propagate=propagate, interval=interval, no_ack=no_ack)
        if callback:
            callback(result.id, value)
        else:
            results.append(value)
    return results