diff --git a/src/core/control.py b/src/core/control.py
index 9adac8ccb13bcb0637b205d332a35aa738a2bdaa..516fdc39c5437eb4fc1df50f8851953e89615609 100644
--- a/src/core/control.py
+++ b/src/core/control.py
@@ -248,14 +248,19 @@ class EngineExecutor(Timer):
                 self.start()
 
 
+    def on_ready(self, func):
+        """
+        Calls the passed function `func` when the timer is ready.
+        """
+        self.join()
+        func()
+
+
     def wait_for_parent(self):
         """
         Child timers are dependend on their parents. So let's wait until parents are done with their stuff.
         """
         if self.parent_timer:
-            # Wait a bit to allow any parent to complete initialization, in case child & parent are instantiated at the 'same' time
-            # Required to avoid "Thread.__init__() not called" exceptions on the parent
-            time.sleep(0.1)
             while self.parent_timer.is_alive():
                 self.logger.info(f"Timer '{self.timer_id}' is waiting for parent timer '{self.parent_timer.timer_id}' to finish")
                 time.sleep(0.2)
diff --git a/src/scheduling/scheduler.py b/src/scheduling/scheduler.py
index 5fb0d4454c4b69a92eae2a26299a8ea517f1267c..6e81b39e35089748932f24da57240c5e07e421b6 100644
--- a/src/scheduling/scheduler.py
+++ b/src/scheduling/scheduler.py
@@ -471,9 +471,9 @@ class PlayCommand(EngineExecutor):
 
         start_preload = entries[0].start_unix - self.config.get("preload_offset")
         start_play = entries[0].start_unix
-        super().__init__("PLAY", None, start_preload, self.do_preload, entries)
-        EngineExecutor("PLAY", self, start_play, self.do_play, entries)
-
+        preload_timer = super().__init__("PLAY", None, start_preload, self.do_preload, entries)
+        self.on_ready(lambda: EngineExecutor("PLAY", self, start_play, self.do_play, entries))
+        
 
     def do_preload(self, entries):
         """