How does Quartz monitor the completion of a trigger? - quartz-scheduler

I try to use TriggerListener to get TriggerState after each execution but it is always Normal, the trigger is released after execution ends.
#Override
public void triggerComplete(Trigger trigger, JobExecutionContext context, Trigger.CompletedExecutionInstruction triggerInstructionCode) {
try {
Trigger.TriggerState state = context.getScheduler().getTriggerState(trigger.getKey());
log.info("state:{}", state);
} catch (SchedulerException e) {
throw new RuntimeException(e);
}
}
How do I know that the trigger has finished executing?

I'm so stupid.The time of the next trigger can be obtained through trigger.getNextFireTime(), if there is no next time, it will return null.

Related

Unity Editor detect when build fails

I'm trying to use IPreProcessBuildWithReport and IPostProcessBuildWithReport to add a game object to the scene right before build, and promptly delete it from the scene when the build finishes. The goal is to reduce all that I can from the hierarchy during the development but include these objects during the build.
My issue occurs when the build fails (due to some error), it adds the game object before the build started but never reached the code to delete the game object when it fails.
Is there a similar method to detect when the build fails without building my own build player pipeline? I really don't want to stray away from unity's default build pipeline if I don't need to.
If there was no easy way, I was trying to think if maybe there was a way to track the buildfailed exception or error and run a method if it occurs.
Thanks, let me know what you guys think.
EDIT: As requested, here is an example:
class CustomBuildPipeline : MonoBehaviour, IPreprocessBuildWithReport, IPostprocessBuildWithReport
{
public int callbackOrder => 0;
// CALLED BEFORE THE BUILD
public void OnPreprocessBuild(BuildReport report)
{
// Create and add gameobjects to scene
}
// CALLED AFTER THE BUILD
public void OnPostprocessBuild(BuildReport report)
{
// Remove gameobjects from scene once built
}
}
}
PreProcess Interface
PostProcess Interface
I was wondering if there was a possible solution by somehow detecting when this buildexception was thrown and running code following.
EDIT 2: I found this post that has possible solutions, however, it may not be as elegant as I'd prefer. I'll try some things out and report back.
I used the post in the 'EDIT 2' to come up with a decent solution. I don't know if it will work 100% of the time and I would love for someone to correct me if I have chosen a poor solution. This should allow me to run code before the build starts, and if the build fails or succeeds without changing the unity build pipeline.
class CustomBuildPipeline : MonoBehaviour, IPreprocessBuildWithReport, IPostprocessBuildWithReport
{
public int callbackOrder => 0;
// CALLED BEFORE THE BUILD
public void OnPreprocessBuild(BuildReport report)
{
// Start listening for errors when build starts
Application.logMessageReceived += OnBuildError;
}
// CALLED DURING BUILD TO CHECK FOR ERRORS
private void OnBuildError(string condition, string stacktrace, LogType type)
{
if (type == LogType.Error)
{
// FAILED TO BUILD, STOP LISTENING FOR ERRORS
Application.logMessageReceived -= OnBuildError;
}
}
// CALLED AFTER THE BUILD
public void OnPostprocessBuild(BuildReport report)
{
// IF BUILD FINISHED AND SUCCEEDED, STOP LOOKING FOR ERRORS
Application.logMessageReceived -= OnBuildError;
}
}
}
This approach is using a custom build handler, but still uses the default build pipeline.
Use BuildHandler.OnBuildStarted instead of (or in addition to) IPreprocessBuildWithReport for pre-processing. For post-processing use BuildHandler.OnBuildCleanup, which is called when a build completes or fails. Can also be used in conjunction with IPostprocessBuildWithReport.
[InitializeOnLoad]
public class BuildHandler : MonoBehaviour
{
public static event Action OnBuildStarted;
public static event Action OnBuildCleanup;
static BuildHandler()
{
BuildPlayerWindow.RegisterBuildPlayerHandler(Build);
}
private static void Build(BuildPlayerOptions buildOptions)
{
try
{
BuildStarted();
//now start Unity's default building procedure
BuildPlayerWindow.DefaultBuildMethods.BuildPlayer(buildOptions);
}
catch (BuildPlayerWindow.BuildMethodException) { } //logged internally
catch (Exception ex)
{
Exception log = ex.InnerException == null ? ex : ex.InnerException;
Debug.LogException(log);
Debug.LogErrorFormat("{0} in BuildHandler: '{1}'", log.GetType().Name, ex.Message);
}
finally
{
BuildCleanup();
}
}
private static void BuildStarted()
{
try
{
if (OnBuildStarted != null)
OnBuildStarted.Invoke();
}
catch (Exception ex)
{
throw new Exception("OnBuildStarted failed", ex);
}
}
private static void BuildCleanup()
{
if (OnBuildCleanup != null)
{
foreach (Action cleanupBuild in OnBuildCleanup.GetInvocationList())
{
try
{
cleanupBuild.Invoke();
}
catch (Exception ex)
{
Object context = cleanupBuild.Target as Object;
Debug.LogException(ex, context);
Debug.LogWarning("Caught exception while BuildHandler.OnBuildCleanup... Continuing");
}
}
}
}
}

SWT: Changing the background color of a label two times

My problem is to change a background color in a runnable. I am trying to change the background color of a label like traffic lights do (red -> yellow -> green) and I have not much experience with SWT. So I do not see why my attempt doesn't work:
Display.getDefault().asyncExec(new Runnable() {
public void run()
{
label.setBackground(red);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
label.setBackground(yellow);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
label.setBackground(green);
}
});
What happens is that nothing is changing during the waiting time (2*1 second) and the last color (in this case green) is shown - no red and no yellow. Could you please give me a hint what my mistake is? Or an idea how to solve this problem?
Display.asyncExec runs the entire Runnable in the User Interface thread. So your two Thread.sleep calls run in the UI thread and stop the thread from updating the UI.
To do something with a delay use the timerExec method of Display to schedule a Runnable to run after a delay.
// Set first color. Note: use `asyncExec` if you are not in the UI thread
label.setBackground(red);
// Schedule changes
Display.getDefault().timerExec(1000, new Runnable() {
#Override
public void run()
{
if (!label.isDisposed()) {
label.setBackground(yellow);
}
}
});
Display.getDefault().timerExec(2000, new Runnable() {
#Override
public void run()
{
if (!label.isDisposed()) {
label.setBackground(green);
}
}
});

Application.Load is not immediate

I have two functions:
private void Function1()
{
Function2();
// Do other stuff here which gets executed
}
private void Function2()
{
Application.LoadLevel("Level");
}
I had always lived in the thought that calling Application.LoadLevel() is immediate, but instead the other stuff in the Function1 does get executed.
Has this been changed in recent versions or has it always been there?
Application.LoadLevel is immediate in the sense that frames aren't generated until the level is loaded, but the current frame still ends.
This means that code register to execute will get executed.
It won't stop the current method from ending.
You could use coroutines to achieve that effect.
private void Function1()
{
StarCoroutine(Coroutine1());
}
private void Function2()
{
Application.LoadLevel("Level");
}
private IEnumerator Coroutine1()
{
Function2();
yield return null;
// Do other stuff here which gets executed
}

Eclipse RCP-- how to do Pause/Resume button functionality with threads using(wait and notify)

Problem statement:--
I have a UI button "Perform"-- which will initiate a big background process in loop in a different thread sequentially.
As soon the process is started the button text will be toggled to "Pause"
Now on press of "Pause", I need to suspend the thread execution and "Resume" will finally notify to go ahead.
On button press"Perform",thread gets started, and button toggles to "Pause" and if I press Pause,thread is suspended.But I am not able to resume the running thread.If I check the Thread state in resume button press event, I get value=0 which is equivalent to NONe. Please help. Following is my code....
Blockquote
performBButton.addSelectionListener(new SelectionListener() {
#Override
public void widgetSelected(SelectionEvent e) {
Button btnToggle = (Button) e.getSource();
MyJob myJob = new MyJob();
if (btnToggle.getText().equalsIgnoreCase("Perform")) {
btnToggle.setText("Pause");
myJob.schedule();
}
else if (btnToggle.getText().equals("Pause")) {
buttonToggle.setText("Resume");
isPaused=!isPaused;
}
else if (btnToggle.getText().equals("Resume")) {
buttonToggle.setText("Pause");
isPaused=!isPaused;
synchronized (myJob) {
myJob.notify();
}
}
}
});
class MYJob extends Job{
public void run(IProgessMonito monitor) {
#Override
public void run() {
for (int i=0;i<50000;i++) {
System.out.println("Iteration "+i +isPaused);
synchronized (this) {
if (isPaused) {
wait();
}
}
}
Thread.sleep(1000);//I have removed try catch while pasting here
}
}
}
}
changing wait() to myThread.wait() actually solved my problem, by declaring myThread globally. but its not the correct way , any further suggestions will be helpful...

How can I correctly update a progress bar for an operation of unknown duration within an Eclipse wizard?

I have implemented a wizard for my Eclipse plug-in, showing several pages. One of these pages needs some lengthy initialization, that means it consists of a SWT table, which needs to be populated by information coming from an external source. This source needs to be activated first (one single method call that returns after a couple of seconds - I can not know in advance how long it will take exactly), before it can be used as input for for the table viewer. This initialization is currently done by the table model provider when it needs to access the external source for the first time.
Therefore, when I enter the wizard page, I would like to show a dummy progress bar that just counts up for a while. My approach was the following, but unfortunately does not work at all:
private void initViewer() {
IRunnableWithProgress runnable = new IRunnableWithProgress() { // needed to embed long running operation into the wizard page
#Override
public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
SubMonitor progress = SubMonitor.convert(monitor);
Thread thread = new Thread() {
#Override
public void run() {
Display.getDefault().syncExec(new Runnable() {
public void run() {
viewer.setInput(ResourcesPlugin.getWorkspace().getRoot()); // this will make the table provider initialize the external source.
}
});
}
};
thread.start();
while(thread.isAlive()) {
progress.setWorkRemaining(10000);
progress.worked(1);
}
progress.done();
}
};
try {
getContainer().run(false, false, runnable);
} catch(Exception e) {
throw new Exception("Could not access data store", e);
}
}
This method gets then invoked when the wizard page's setVisible()-method is called and should, after a couple of seconds, set the viewer's input. This, however, never happens, because the inner-most run()-method never gets executed.
Any hints on how to deal with long-running (where an exact estimate is not available) initializations in Eclipse wizards would be very appreciated!
I have given below a simple example on how to use IRunnableWithProgress along with a ProgressMonitorDialog to perform a task of unknown quantity. To start with, have an implementation to IRunnableWithProgress from where the actual task is performed. This implementation could be an inner class.
public class MyRunnableWithProgress implements IRunnableWithProgress {
private String _fileName;
public MyRunnableWithProgress(String fileName) {
_fileName = fileName;
}
#Override
public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
int totalUnitsOfWork = IProgressMonitor.UNKNOWN;
monitor.beginTask("Performing read. Please wait...", totalUnitsOfWork);
performRead(_fileName, monitor); // This only performs the tasks
monitor.done();
}
}
Now, a generic implementation to ProgressMonitorDialog can be created as below which could be used for other places where a progress monitor dialog is required.
public class MyProgressMonitorDialog extends ProgressMonitorDialog {
private boolean cancellable;
public MyProgressMonitorDialog(Shell parent, boolean cancellable) {
super(parent);
this.cancellable = cancellable;
}
#Override
public Composite createDialogArea(Composite parent) {
Composite container = (Composite) super.createDialogArea(parent);
setCancelable(cancellable);
return container;
}
}
Having got the required implementation, the task can be invoked as below to get it processed with a progress dialog.
boolean cancellable = false;
IRunnableWithProgress myRunnable = new MyRunnableWithProgress(receivedFileName);
ProgressMonitorDialog progressMonitorDialog = new MyProgressMonitorDialog(getShell(), cancellable);
try {
progressMonitorDialog.run(true, true, myRunnable);
} catch (InvocationTargetException e) {
// Catch in your best way
throw new RuntimeException(e);
} catch (InterruptedException e) {
//Catch in your best way
Thread.currentThread().interrupt();
}
Hope this helps!
I assume the reason why it's "not working" for you is that the preparation of input is done in UI thread meaning that the progress bar cannot be updated. A better approach is to prepare input in advance and only set input to viewer after that.