<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def listener(self, channels=None, patterns=None, is_async=False):
 """ Decorator for wrapping functions used to listen for Redis pub-sub messages. The listener will listen until the decorated function raises a ``StopIteration`` exception. :param list channels: Channels to listen on. :param list patterns: Patterns to match. :param bool is_async: Whether to start the listener in a separate thread. """

        def decorator(fn):
            _channels = channels or []
            _patterns = patterns or []

            @wraps(fn)
            def inner():
                pubsub = self.pubsub()

                def listen():
                    for channel in _channels:
                        pubsub.subscribe(channel)
                    for pattern in _patterns:
                        pubsub.psubscribe(pattern)

                    for data_dict in pubsub.listen():
                        try:
                            ret = fn(**data_dict)
                        except StopIteration:
                            pubsub.close()
                            break

                if is_async:
                    worker = threading.Thread(target=listen)
                    worker.start()
                    return worker
                else:
                    listen()

            return inner
        return decorator