If your wait() doesn’t work, it’s probably due to exception that wasn’t caught. Catch it.
with ThreadPoolExecutor() as executor:
futures = {r.name: executor.submit(r.execute) for r in self.runs}
wait(futures.values())
for name, f in futures.items():
if f.exception():
logger.error(
f"Exception occurred in {name}", exc_info=f.exception()
)