How to schedule AnActionEvent actions?

Hello,

I'm trying to a create a plugin that runs an action every few seconds or so. I've used the regular scheduler:

AppExecutorUtil.getAppScheduledExecutorService().scheduleWithFixedDelay(new Runnable() {
@Override
public void run() {/* run your code here */}
}, 1, 3L , SECONDS);

but would like access to which line the cursor is on and which document is being viewed, etc that the AnActionEvent object gives you access to. How do you schedule AnActionEvent tasks?

Thank you

15 comments
Official comment

Please try ActionManager#tryToExecute, it should work. You can pass null as contextComponent, then currently focused component will be used to build DataContext.

Thanks for that tip, however I'm still having trouble.

I have the call to ActionManager#tryToExecute set up like this: With GatherData being my class that extends AnAction

ActionManager.getInstance().tryToExecute(new GatherData(), ActionCommand.getInputEvent("NewFromTemplate"), null, null, true);

 

I've also tried putting this into initComponent() in GatherData like this

ActionManager.getInstance().tryToExecute(new GatherData.this, ActionCommand.getInputEvent("NewFromTemplate"), null, null, true);

I've also tried putting this into initComponent() in GatherData like this

But still the GatherData.actionPerformed() doesn't run. Any tips Peter? I feel like I'm going at this all wrong.

0

The code looks like it should work. Maybe the action isn't enabled? I can only suggest to put breakpoints inside tryToExecute and understand what's going on.

0

I'm still having trouble, is there a way to know if your action is enabled or not at the time of running tryToExecute?

0

I took it out of the scheduler and I got this error:

java.lang.AssertionError
at com.intellij.openapi.actionSystem.impl.ActionManagerImpl.tryToExecute(ActionManagerImpl.java:1259)
at MyPreloadingActivity.preload(MyPreloadingActivity.java:41)
at com.intellij.openapi.application.Preloader.a(Preloader.java:74)
at com.intellij.openapi.progress.impl.CoreProgressManager.a(CoreProgressManager.java:157)
at com.intellij.openapi.progress.impl.CoreProgressManager.a(CoreProgressManager.java:543)
at com.intellij.openapi.progress.impl.CoreProgressManager.executeProcessUnderProgress(CoreProgressManager.java:488)
at com.intellij.openapi.progress.impl.ProgressManagerImpl.executeProcessUnderProgress(ProgressManagerImpl.java:94)
at com.intellij.openapi.progress.impl.CoreProgressManager.runProcess(CoreProgressManager.java:144)
at com.intellij.openapi.application.Preloader.a(Preloader.java:72)
at com.intellij.util.concurrency.BoundedTaskExecutor$2.run(BoundedTaskExecutor.java:212)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)

 

Any advice on how to find the code inside tryToExecute so I can start putting breakpoints in?

0

Figured it out, it probably wasn't enabled. need to find a way to run the scheduled task only when my action is enabled. If there's a way to check for it, let me know.

0

The assertion error you're getting means that you're not on Swing dispatch thread. You should invoke tryToExecute on that thread. EdtExecutor can help with that.

The scheduled task itself checks if your action is enabled and doesn't run the action otherwise.

0

So I've been stumped on this for a few days now, when I run the action at the exact same moment like this it runs fine and the action completes, I can run it many times in a row without problems:


System.out.println("Scheduled Task Running...");
AnAction action = ActionManager.getInstance().getAction("RightClickButton");
InputEvent inputEvent = ActionCommand.getInputEvent("RightClickButton");
ActionCallback callback = ActionManager.getInstance().tryToExecute(action, inputEvent, null, null, true);
System.out.println(callback.toString());
System.out.println("finished attempt to run GatherData");

However when I try to schedule the action like so, the action doesn't get run, it prints "Scheduled Task Running" and hangs on the tryToExecute line, never to run again. 

AppExecutorUtil.getAppScheduledExecutorService().scheduleWithFixedDelay(new Runnable() {
@Override
public void run() {
System.out.println("Scheduled Task Running...");
AnAction action = ActionManager.getInstance().getAction("RightClickButton");
InputEvent inputEvent = ActionCommand.getInputEvent("RightClickButton");
ActionCallback callback = ActionManager.getInstance().tryToExecute(action, inputEvent, null, null, true);
System.out.println(callback.toString());
System.out.println("finished attempt to run GatherData");
}
}, 15, 3L , SECONDS);

is there something fundamentally wrong with trying to run tryToExecute within scheduleWithFixedDelay, it's almost as if it doesn't have access to something when run inside the scheduler. Any tips anyone?

Thanks for your help by the way.

0

As I've already written, you're not on Swing dispatch thread. You should invoke tryToExecute on that thread. EdtExecutor can help with that.

0

EdtExecutor worked! for anyone wondering what to replace AppExecutorUtil with, here's what I did

//AppExecutorUtil.getAppScheduledExecutorService().scheduleWithFixedDelay // bad thread, doesn't work
EdtExecutorService.getScheduledExecutorInstance().scheduleWithFixedDelay(new Runnable() {

However I've run into a separate problem with tryToExecute. It hangs after running, no matter if it's in the scheduler or not. It runs the action and never gets over to the next line. Any ideas?

0

Please try putting breakpoints and debugging.

0

I have, what it does is beyond me however I will try to explain.

ActionCallback callback = ActionManager.getInstance().tryToExecute(action, inputEvent, null, null, true);

After stepping over this line, a new window with SchedulingWrapper.class opens up with this line:

} else if (this.runAndReset()) {

highlighted in run(). here is the whole run function I am shown in SchedulingWrapper.class:

public void run() {
if (SchedulingWrapper.LOG.isTraceEnabled()) {
SchedulingWrapper.LOG.trace("Executing " + BoundedTaskExecutor.info(this));
}

boolean periodic = this.isPeriodic();
if (!periodic) {
super.run();
} else if (this.runAndReset()) {
this.setNextRunTime();
this.this$0.delayQueue.offer(this);
}

}

after two more steps I am shown this line in IdeEventQueue.class

private void h(@org.jetbrains.annotations.NotNull java.awt.AWTEvent awtEvent) { /* compiled code */ }

and then in two more steps, in the same class

public void _dispatchEvent(@org.jetbrains.annotations.NotNull java.awt.AWTEvent awtEvent, boolean b) { /* compiled code */ }

then the next steps just keep showing that above line about 10 steps until stepping forward doesn't highlight any line or go anywhere. 

 

0

I just want to add, during debugging, I noticed in the SchedulingWrapper.class frame, if I inspect the variables, this.outcome is a Java.lang.AssertionError

So it looks like there's an Assertion Error, but it's not preventing the task from running, just from finishing.

0

I think I found the problem. it's these lines within the action itself:

try {
editor = event.getRequiredData(LangDataKeys.EDITOR);
} catch (Exception e) {e.printStackTrace();}

specifically the event.getRequiredData(LangDataKeys.EDITOR) part. Try to execute has a problem with that apparently and only when the editor is not selected. Is there any way to check for the focus of the editor within the AnActionEvent before trying to extract it? seems as soon as you try to run that getRequiredData line the scheduler craps out.

Thanks for your patience with me.

0

Fixed, use getData instead of getRequiredData and try catch blocks worked. Thanks all.

0

Please sign in to leave a comment.