CompletableFuture<R> ( @NotNull Function<@NotNull ProgressIndicator, R> task, @NotNull CompletableFuture<? extends @NotNull ProgressIndicator> progressIndicatorFuture ) { CompletableFuture<R> resultFuture = new CompletableFuture<>(); ChildContext childContext = Propagation.createChildContext(); CoroutineContext context = childContext.getContext(); Job job = childContext.getJob(); if (job != null) { // cancellation of the Job cancels the future job.invokeOnCompletion(true, true, (throwable) -> { if (throwable != null) { resultFuture.completeExceptionally(throwable); } return Unit.INSTANCE; }); } progressIndicatorFuture.whenComplete((progressIndicator, throwable) -> { if (throwable != null) { resultFuture.completeExceptionally(throwable); return; } Runnable runnable = new ProgressRunnable<>(resultFuture, task, progressIndicator); Runnable contextRunnable = context.equals(EmptyCoroutineContext.INSTANCE) ? runnable : (ContextAwareRunnable)() -> { CoroutineContext effectiveContext = context.plus(asContextElement(progressIndicator.getModalityState())); try (AccessToken ignored = ThreadContext.installThreadContext(effectiveContext, false)) { childContext.runAsCoroutine(runnable); } }; switch (myThreadToUse) { case POOLED: AppExecutorUtil.getAppExecutorService().execute(contextRunnable); break; case WRITE: ModalityState processModality = progressIndicator.getModalityState(); ApplicationManager.getApplication().invokeLaterOnWriteThread(contextRunnable, processModality); break; default: throw new IllegalStateException("Unexpected value: " + myThreadToUse); } }); return resultFuture; }