void (@NotNull String TOMB_STONE, @NotNull BlockingQueue<String> queue, @NotNull Queue<String> failedQueue) { while (true) { Disposable disposable = Disposer.newDisposable(); ProgressIndicator wrapper = new DaemonProgressIndicator(); try { // avoid "attach listener"/"write action" race ReadAction.run(() -> { wrapper.start(); ProgressIndicatorUtils.forceWriteActionPriority(wrapper, disposable); // there is a chance we are racing with write action, in which case just registered listener might not be called, retry. if (ApplicationManagerEx.getApplicationEx().isWriteActionPending()) { throw new ProcessCanceledException(); } }); // use wrapper here to cancel early when write action start but do not affect the original indicator ((JobLauncherImpl)JobLauncher.getInstance()).processQueue(queue, failedQueue, wrapper, TOMB_STONE, __ -> { ReadAction.run(() -> { ProgressManager.checkCanceled(); //TimeoutUtil.sleep(1); ProgressManager.checkCanceled(); COUNT.incrementAndGet(); }); return true; }); break; } catch (ProcessCanceledException e) { // wait for write action to complete ApplicationManager.getApplication().runReadAction(EmptyRunnable.getInstance()); } finally { Disposer.dispose(disposable); } } }