code: def _launch_job_function(self, job, func_args=None):
      # type: (BaseScheduleJob, Optional[Sequence]) -> Optional[Thread]
      # make sure this IS a function job
      if not job.base_function:
          return None
  
      # check if this is a single instance, then we need to abort the Task
      if job.single_instance and job.get_last_executed_task_id():
          # noinspection PyBroadException
          try:
              a_thread = [
                  t
                  for t in enumerate_threads()
                  if t.ident == job.get_last_executed_task_id()
              ]
              if a_thread:
                  a_thread = a_thread[0]
          except Exception:
              a_thread = None
  
          if a_thread and a_thread.is_alive():
              self._log(
                  "Skipping Task '{}' scheduling, previous Thread instance '{}' still running".format(
                      job.name, a_thread.ident
                  )
              )
              job.run(None)
              return None
  
      self._log(
          "Scheduling Job '{}', Task '{}' on background thread".format(
              job.name, job.base_function
          )
      )
      t = Thread(target=job.base_function, args=func_args or ())
      t.start()
      # mark as run
      job.run(t.ident)
      return t
  
imports: import json
  import logging
  from datetime import datetime
  from threading import Thread, enumerate
  from time import sleep, time
  from typing import List, Union, Optional, Callable, Sequence, Dict
  from attr import attrs, attrib
  from dateutil.relativedelta import relativedelta
  from .job import ClearmlJob
  from .controller import PipelineController
  from ..backend_interface.util import datetime_from_isoformat, datetime_to_isoformat, mutually_exclusive
  from ..task import Task
label_desc: Use image node_id 13 for calling the BaseScheduler obj's underlying member method code with example usage: obj._launch_job_function(job, func_args) and returns: t, None, None