code: def _dequeue_batch(self) -> Optional[Batch]:
          
          if self._enqueueing_thread is None:
              raise ValueError('StreamWrapper `{}` with buffer of size `{}` was used outside with-resource environment.'
                               .format(self._name, self._buffer_size))
          if not self._enqueueing_thread.is_alive() and self._queue.empty():
              self._start_thread()
          while True:
              try:
                  batch = self._queue.get(timeout=2)
                  self._queue.task_done()
                  break
              except Empty:
                  if not self._enqueueing_thread.is_alive():
                      try:
                          # the enqueueing thread may just finished properly so lets check the queue eagerly
                          batch = self._queue.get_nowait()
                          self._queue.task_done()
                          break
                      except Empty:
                          # so we failed to retrieve a batch and the enqueueing thread is dead
                          # there is no hope, something must went wrong
                          raise ChildProcessError('Enqueueing thread ended unexpectedly.')
          return batch
docs: Return a single batch from queue or ``None`` signaling epoch end.
  
          :raise ChildProcessError: if the enqueueing thread ended unexpectedly