When do I schedule a ReadTask?
I have some analysis that I want to run every time the current file changes. The analysis can take a few seconds, so I need to cancel it whenever the user types more, then restart the analysis.
In the documentation for ReadTask, it says to schedule another task if it gets cancelled before finishing. I wrote a little example task that just runs a timer for five seconds while checking for cancellation. When I look at the log, I see it gets cancelled and restarted several times, and then it runs for a few seconds. If I type another letter before it finishes, it gets cancelled and restarts, but the documentChanged() handler schedules a second task. Now I have two sets of tasks running in parallel, each cancelling and restarting several times before they can get started. If I type a third letter, I end up with three tasks in parallel.
Do I have to check whether the analysis has finished in documentChanged(), and only schedule a new task if the old one finished? Is it normal for there to be so many write actions that keep cancelling my analysis? Is there an easier strategy for running a background task? How do the code inspections run?
Here's my little example:
private void logThread(String message) {
String name = Thread.currentThread().getName();
if (name.length() > 35) {
name = name.substring(0, 35);
}
log.info(String.format(
"[%s] %s",
name,
message));
}
private class AnalysisTask extends ReadTask {
private Document document;
AnalysisTask(Document document) {
this.document = document;
}
@Nullable
@Override
public Continuation performInReadAction(@NotNull ProgressIndicator indicator) throws ProcessCanceledException {
String sourceCode = document.getText();
logThread("Starting " + toString() + " with " + sourceCode);
for (int i = 0; i < 500; i++) {
try {
Thread.sleep(10);
indicator.checkCanceled();
} catch (ProcessCanceledException | InterruptedException e) {
logThread("cancelled " + toString() + " with " + sourceCode);
return null;
}
}
logThread("Finished " + toString() + " with " + sourceCode);
return null;
}
@Override
public void onCanceled(@NotNull ProgressIndicator indicator) {
logThread("onCanceled " + toString());
schedule(document);
}
}
@Override
public void documentChanged(DocumentEvent e) {
if (isRunning) {
logThread("document changed");
schedule(e.getDocument());
}
}
private void schedule(Document document) {
ProgressIndicatorUtils.scheduleWithWriteActionPriority(new AnalysisTask(document));
}
Here is the log output when I type "abc" into an empty file:
2017-10-27 21:25:51,080 [ 559075] INFO - .livepycharm.LiveCodingAnalyst - [AWT-EventQueue-0 2017.1.4#IC-171.46] document changed
2017-10-27 21:25:51,085 [ 559080] INFO - .livepycharm.LiveCodingAnalyst - [ApplicationImpl pooled thread 21] Starting ...AnalysisTask@7a021782 with a
2017-10-27 21:25:51,085 [ 559080] INFO - .livepycharm.LiveCodingAnalyst - [AWT-EventQueue-0 2017.1.4#IC-171.46] onCanceled ...AnalysisTask@7a021782
2017-10-27 21:25:51,095 [ 559090] INFO - .livepycharm.LiveCodingAnalyst - [ApplicationImpl pooled thread 21] cancelled ...AnalysisTask@7a021782 with a
2017-10-27 21:25:51,097 [ 559092] INFO - .livepycharm.LiveCodingAnalyst - [ApplicationImpl pooled thread 21] Starting ...AnalysisTask@75f6e03 with a
2017-10-27 21:25:51,100 [ 559095] INFO - .livepycharm.LiveCodingAnalyst - [AWT-EventQueue-0 2017.1.4#IC-171.46] onCanceled ...AnalysisTask@75f6e03
2017-10-27 21:25:51,108 [ 559103] INFO - .livepycharm.LiveCodingAnalyst - [ApplicationImpl pooled thread 21] cancelled ...AnalysisTask@75f6e03 with a
2017-10-27 21:25:51,110 [ 559105] INFO - .livepycharm.LiveCodingAnalyst - [ApplicationImpl pooled thread 21] Starting ...AnalysisTask@3ddd9096 with a
2017-10-27 21:25:51,110 [ 559105] INFO - .livepycharm.LiveCodingAnalyst - [AWT-EventQueue-0 2017.1.4#IC-171.46] onCanceled ...AnalysisTask@3ddd9096
2017-10-27 21:25:51,120 [ 559115] INFO - .livepycharm.LiveCodingAnalyst - [ApplicationImpl pooled thread 21] cancelled ...AnalysisTask@3ddd9096 with a
2017-10-27 21:25:51,121 [ 559116] INFO - .livepycharm.LiveCodingAnalyst - [ApplicationImpl pooled thread 21] Starting ...AnalysisTask@5bad3529 with a
2017-10-27 21:25:52,087 [ 560082] INFO - .livepycharm.LiveCodingAnalyst - [AWT-EventQueue-0 2017.1.4#IC-171.46] onCanceled ...AnalysisTask@5bad3529
2017-10-27 21:25:52,092 [ 560087] INFO - .livepycharm.LiveCodingAnalyst - [ApplicationImpl pooled thread 21] cancelled ...AnalysisTask@5bad3529 with a
2017-10-27 21:25:52,094 [ 560089] INFO - .livepycharm.LiveCodingAnalyst - [AWT-EventQueue-0 2017.1.4#IC-171.46] document changed
2017-10-27 21:25:52,101 [ 560096] INFO - .livepycharm.LiveCodingAnalyst - [ApplicationImpl pooled thread 2] Starting ...AnalysisTask@6e7fa33d with ab
2017-10-27 21:25:52,107 [ 560102] INFO - .livepycharm.LiveCodingAnalyst - [ApplicationImpl pooled thread 18] Starting ...AnalysisTask@39268d1b with ab
2017-10-27 21:25:52,107 [ 560102] INFO - .livepycharm.LiveCodingAnalyst - [AWT-EventQueue-0 2017.1.4#IC-171.46] onCanceled ...AnalysisTask@6e7fa33d
2017-10-27 21:25:52,107 [ 560102] INFO - .livepycharm.LiveCodingAnalyst - [AWT-EventQueue-0 2017.1.4#IC-171.46] onCanceled ...AnalysisTask@39268d1b
2017-10-27 21:25:52,111 [ 560106] INFO - .livepycharm.LiveCodingAnalyst - [ApplicationImpl pooled thread 2] cancelled ...AnalysisTask@6e7fa33d with ab
2017-10-27 21:25:52,117 [ 560112] INFO - .livepycharm.LiveCodingAnalyst - [ApplicationImpl pooled thread 18] cancelled ...AnalysisTask@39268d1b with ab
2017-10-27 21:25:52,119 [ 560114] INFO - .livepycharm.LiveCodingAnalyst - [ApplicationImpl pooled thread 2] Starting ...AnalysisTask@24b2a450 with ab
2017-10-27 21:25:52,119 [ 560114] INFO - .livepycharm.LiveCodingAnalyst - [ApplicationImpl pooled thread 18] Starting ...AnalysisTask@2bb75a5b with ab
2017-10-27 21:25:53,325 [ 561320] INFO - .livepycharm.LiveCodingAnalyst - [AWT-EventQueue-0 2017.1.4#IC-171.46] onCanceled ...AnalysisTask@2bb75a5b
2017-10-27 21:25:53,325 [ 561320] INFO - .livepycharm.LiveCodingAnalyst - [AWT-EventQueue-0 2017.1.4#IC-171.46] onCanceled ...AnalysisTask@24b2a450
2017-10-27 21:25:53,328 [ 561323] INFO - .livepycharm.LiveCodingAnalyst - [ApplicationImpl pooled thread 18] cancelled ...AnalysisTask@2bb75a5b with ab
2017-10-27 21:25:53,328 [ 561323] INFO - .livepycharm.LiveCodingAnalyst - [ApplicationImpl pooled thread 2] cancelled ...AnalysisTask@24b2a450 with ab
2017-10-27 21:25:53,330 [ 561325] INFO - .livepycharm.LiveCodingAnalyst - [AWT-EventQueue-0 2017.1.4#IC-171.46] document changed
2017-10-27 21:25:53,339 [ 561334] INFO - .livepycharm.LiveCodingAnalyst - [ApplicationImpl pooled thread 18] Starting ...AnalysisTask@73b4e4d5 with abc
2017-10-27 21:25:53,342 [ 561337] INFO - .livepycharm.LiveCodingAnalyst - [ApplicationImpl pooled thread 2] Starting ...AnalysisTask@4a7674b1 with abc
2017-10-27 21:25:53,344 [ 561339] INFO - .livepycharm.LiveCodingAnalyst - [ApplicationImpl pooled thread 22] Starting ...AnalysisTask@5cb85d77 with abc
2017-10-27 21:25:53,344 [ 561339] INFO - .livepycharm.LiveCodingAnalyst - [AWT-EventQueue-0 2017.1.4#IC-171.46] onCanceled ...AnalysisTask@73b4e4d5
2017-10-27 21:25:53,344 [ 561339] INFO - .livepycharm.LiveCodingAnalyst - [AWT-EventQueue-0 2017.1.4#IC-171.46] onCanceled ...AnalysisTask@4a7674b1
2017-10-27 21:25:53,344 [ 561339] INFO - .livepycharm.LiveCodingAnalyst - [AWT-EventQueue-0 2017.1.4#IC-171.46] onCanceled ...AnalysisTask@5cb85d77
2017-10-27 21:25:53,349 [ 561344] INFO - .livepycharm.LiveCodingAnalyst - [ApplicationImpl pooled thread 18] cancelled ...AnalysisTask@73b4e4d5 with abc
2017-10-27 21:25:53,353 [ 561348] INFO - .livepycharm.LiveCodingAnalyst - [ApplicationImpl pooled thread 2] cancelled ...AnalysisTask@4a7674b1 with abc
2017-10-27 21:25:53,354 [ 561349] INFO - .livepycharm.LiveCodingAnalyst - [ApplicationImpl pooled thread 22] cancelled ...AnalysisTask@5cb85d77 with abc
2017-10-27 21:25:53,356 [ 561351] INFO - .livepycharm.LiveCodingAnalyst - [ApplicationImpl pooled thread 18] Starting ...AnalysisTask@4f93c336 with abc
2017-10-27 21:25:53,356 [ 561351] INFO - .livepycharm.LiveCodingAnalyst - [ApplicationImpl pooled thread 22] Starting ...AnalysisTask@77b39476 with abc
2017-10-27 21:25:53,356 [ 561351] INFO - .livepycharm.LiveCodingAnalyst - [ApplicationImpl pooled thread 2] Starting ...AnalysisTask@70395dcc with abc
2017-10-27 21:25:58,426 [ 566421] INFO - .livepycharm.LiveCodingAnalyst - [ApplicationImpl pooled thread 18] Finished ...AnalysisTask@4f93c336 with abc
2017-10-27 21:25:58,436 [ 566431] INFO - .livepycharm.LiveCodingAnalyst - [ApplicationImpl pooled thread 22] Finished ...AnalysisTask@77b39476 with abc
2017-10-27 21:25:58,436 [ 566431] INFO - .livepycharm.LiveCodingAnalyst - [ApplicationImpl pooled thread 2] Finished ...AnalysisTask@70395dcc with abc
请先登录再写评论。
The easiest way seems to have an Alarm where "cancelAllRequests" and "schedule" are called on both cancellation and document change. Then these events would be merged and only a single bg task would be run (after the alarm timeout passes). Editor highlighting works in a similar way.
Thanks, Peter, I didn't know about the Alarm class.