code: def run(self):
      while (
          self.should_continue_running()
          or not self._values_queue.empty()
      ):
          try:
              sleep_start = time.time()
              self._values_batch.append(
                  self._values_queue.get(
                      timeout=max(self._sleep_time, 0)
                  )
              )
              self._values_queue.task_done()
              self._sleep_time -= time.time() - sleep_start
          except Empty:
              self._sleep_time = 0
  
          image_values_batch_size = sum(
              [
                  len(v.channel_value.y["image_value"]["data"] or [])
                  for v in self._values_batch
                  if v.channel_type == ChannelType.IMAGE.value
              ]
          )
          if (
              self._sleep_time <= 0
              or len(self._values_batch)
              >= self._MAX_VALUES_BATCH_LENGTH
              or image_values_batch_size
              >= self._MAX_IMAGE_VALUES_BATCH_SIZE
          ):
              self._process_batch()
  
      self._process_batch()
  
imports: import logging
  import threading
  import time
  from collections import namedtuple
  from itertools import groupby
  from queue import Empty, Queue
  from bravado.exception import HTTPUnprocessableEntity
  from neptune.legacy.exceptions import NeptuneException
  from neptune.legacy.internal.channels.channels import ChannelIdWithValues, ChannelNamespace, ChannelType, ChannelValue
  from neptune.legacy.internal.threads.neptune_thread import NeptuneThread
label_desc: Use image node_id 2 for calling the ChannelsValuesSendingThread obj's underlying member method code with example usage: obj.run() without return types